Add AAD X.509 cert auth support (#10)
- AAD/Keyvault credential support in credentials.json
This commit is contained in:
Родитель
be04d89410
Коммит
348ceebc65
|
@ -81,10 +81,6 @@ celerybeat-schedule
|
|||
# dotenv
|
||||
.env
|
||||
|
||||
# virtualenv
|
||||
venv/
|
||||
ENV/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
|
||||
|
|
|
@ -49,6 +49,8 @@ for MPI on HPC low-latency Azure VM instances:
|
|||
* [N-Series](https://docs.microsoft.com/en-us/azure/virtual-machines/virtual-machines-windows-sizes?toc=%2fazure%2fvirtual-machines%2fwindows%2ftoc.json#n-series): STANDARD\_NC24R (not yet ready with Linux hosts)
|
||||
* Automatic setup of SSH users to all nodes in the compute pool and optional
|
||||
tunneling to Docker Hosts on compute nodes
|
||||
* Support for credential management through
|
||||
[Azure KeyVault](https://azure.microsoft.com/en-us/services/key-vault/)
|
||||
|
||||
## Installation
|
||||
Installation is typically an easy two-step process. The CLI is also available
|
||||
|
|
|
@ -1,5 +1,18 @@
|
|||
{
|
||||
"credentials": {
|
||||
"keyvault": {
|
||||
"uri": "",
|
||||
"credentials_secret_id": "",
|
||||
"aad": {
|
||||
"directory_id": "",
|
||||
"application_id": "",
|
||||
"auth_key": "",
|
||||
"rsa_private_key_pem": "",
|
||||
"x509_cert_sha1_thumbprint": "",
|
||||
"user": "",
|
||||
"password": ""
|
||||
}
|
||||
},
|
||||
"batch": {
|
||||
"account": "",
|
||||
"account_key": "",
|
||||
|
|
|
@ -157,6 +157,20 @@ def derive_public_key_pem_from_pfx(pfxfile, passphrase=None, pemfile=None):
|
|||
return pemfile
|
||||
|
||||
|
||||
def _parse_sha1_thumbprint_openssl(output):
|
||||
# type: (str) -> str
|
||||
"""Get SHA1 thumbprint from buffer
|
||||
:param str buffer: buffer to parse
|
||||
:rtype: str
|
||||
:return: sha1 thumbprint of buffer
|
||||
"""
|
||||
# return just thumbprint (without colons) from the above openssl command
|
||||
# in lowercase. Expected openssl output is in the form:
|
||||
# SHA1 Fingerprint=<thumbprint>
|
||||
return ''.join(util.decode_string(
|
||||
output).strip().split('=')[1].split(':')).lower()
|
||||
|
||||
|
||||
def get_sha1_thumbprint_pfx(pfxfile, passphrase):
|
||||
# type: (str, str) -> str
|
||||
"""Get SHA1 thumbprint of PFX
|
||||
|
@ -178,12 +192,21 @@ def get_sha1_thumbprint_pfx(pfxfile, passphrase):
|
|||
['openssl', 'x509', '-noout', '-fingerprint'], stdin=subprocess.PIPE,
|
||||
stdout=subprocess.PIPE
|
||||
)
|
||||
sha1_cert_tp = proc.communicate(input=pfxdump)[0]
|
||||
# return just thumbprint (without colons) from the above openssl command
|
||||
# in lowercase. Expected openssl output is in the form:
|
||||
# SHA1 Fingerprint=<thumbprint>
|
||||
return ''.join(util.decode_string(
|
||||
sha1_cert_tp).strip().split('=')[1].split(':')).lower()
|
||||
return _parse_sha1_thumbprint_openssl(proc.communicate(input=pfxdump)[0])
|
||||
|
||||
|
||||
def get_sha1_thumbprint_pem(pemfile):
|
||||
# type: (str) -> str
|
||||
"""Get SHA1 thumbprint of PEM
|
||||
:param str pfxfile: name of the pfx file to export
|
||||
:rtype: str
|
||||
:return: sha1 thumbprint of pem
|
||||
"""
|
||||
proc = subprocess.Popen(
|
||||
['openssl', 'x509', '-noout', '-fingerprint', '-in', pemfile],
|
||||
stdout=subprocess.PIPE
|
||||
)
|
||||
return _parse_sha1_thumbprint_openssl(proc.communicate()[0])
|
||||
|
||||
|
||||
def generate_pem_pfx_certificates(config):
|
||||
|
|
|
@ -49,6 +49,7 @@ import azure.batch.models as batchmodels
|
|||
from . import batch
|
||||
from . import crypto
|
||||
from . import data
|
||||
from . import keyvault
|
||||
from . import settings
|
||||
from . import storage
|
||||
from . import util
|
||||
|
@ -206,6 +207,34 @@ def _create_clients(config):
|
|||
return batch_client, blob_client, queue_client, table_client
|
||||
|
||||
|
||||
def create_keyvault_client(ctx, config):
|
||||
# type: (CliContext, dict) -> azure.keyvault.KeyVaultClient
|
||||
"""Create KeyVault client
|
||||
:param CliContext ctx: Cli Context
|
||||
:param dict config: configuration dict
|
||||
:rtype: azure.keyvault.KeyVaultClient
|
||||
:return: key vault client
|
||||
"""
|
||||
kv = settings.credentials_keyvault(config)
|
||||
aad_directory_id = ctx.aad_directory_id or kv.aad_directory_id
|
||||
aad_application_id = ctx.aad_application_id or kv.aad_application_id
|
||||
aad_auth_key = ctx.aad_auth_key or kv.aad_auth_key
|
||||
aad_user = ctx.aad_user or kv.aad_user
|
||||
aad_password = ctx.aad_password or kv.aad_password
|
||||
aad_cert_private_key = ctx.aad_cert_private_key or kv.aad_cert_private_key
|
||||
aad_cert_thumbprint = ctx.aad_cert_thumbprint or kv.aad_cert_thumbprint
|
||||
# check if no keyvault/aad params were specified at all
|
||||
if (aad_directory_id is None and aad_application_id is None and
|
||||
aad_auth_key is None and aad_user is None and
|
||||
aad_password is None and aad_cert_private_key is None and
|
||||
aad_cert_thumbprint is None):
|
||||
return None
|
||||
else:
|
||||
return keyvault.create_client(
|
||||
aad_directory_id, aad_application_id, aad_auth_key, aad_user,
|
||||
aad_password, aad_cert_private_key, aad_cert_thumbprint)
|
||||
|
||||
|
||||
def initialize(config):
|
||||
# type: (dict) -> tuple
|
||||
"""Initialize fleet and create authenticated clients
|
||||
|
@ -218,6 +247,35 @@ def initialize(config):
|
|||
return _create_clients(config)
|
||||
|
||||
|
||||
def fetch_credentials_json_from_keyvault(
|
||||
keyvault_client, keyvault_uri, keyvault_credentials_secret_id):
|
||||
# type: (azure.keyvault.KeyVaultClient, str, str) -> dict
|
||||
"""Fetch a credentials json from keyvault
|
||||
:param azure.keyvault.KeyVaultClient keyvault_client: keyvault client
|
||||
:param str keyvault_uri: keyvault uri
|
||||
:param str keyvault_credentials_secret_id: keyvault cred secret id
|
||||
:rtype: dict
|
||||
:return: credentials json
|
||||
"""
|
||||
if keyvault_uri is None:
|
||||
raise ValueError('credentials json was not specified or is invalid')
|
||||
if keyvault_client is None:
|
||||
raise ValueError('no Azure KeyVault or AAD credentials specified')
|
||||
return keyvault.fetch_credentials_json(
|
||||
keyvault_client, keyvault_uri, keyvault_credentials_secret_id)
|
||||
|
||||
|
||||
def fetch_secrets_from_keyvault(keyvault_client, config):
|
||||
# type: (azure.keyvault.KeyVaultClient, dict) -> None
|
||||
"""Fetch secrets with secret ids in config from keyvault
|
||||
:param azure.keyvault.KeyVaultClient keyvault_client: keyvault client
|
||||
:param dict config: configuration dict
|
||||
"""
|
||||
if keyvault_client is None:
|
||||
raise ValueError('no Azure KeyVault or AAD credentials specified')
|
||||
keyvault.parse_secret_ids(keyvault_client, config)
|
||||
|
||||
|
||||
def _setup_nvidia_driver_package(blob_client, config, vm_size):
|
||||
# type: (azure.storage.blob.BlockBlobService, dict, str) -> pathlib.Path
|
||||
"""Set up the nvidia driver package
|
||||
|
@ -1037,6 +1095,37 @@ def _adjust_settings_for_pool_creation(config):
|
|||
pass
|
||||
|
||||
|
||||
def action_keyvault_add(keyvault_client, config, keyvault_uri, name):
|
||||
# type: (azure.keyvault.KeyVaultClient, dict, str, str) -> None
|
||||
"""Action: Keyvault Add
|
||||
:param azure.keyvault.KeyVaultClient keyvault_client: keyvault client
|
||||
:param dict config: configuration dict
|
||||
:param str keyvault_uri: keyvault uri
|
||||
:param str name: secret name
|
||||
"""
|
||||
keyvault.store_credentials_json(
|
||||
keyvault_client, config, keyvault_uri, name)
|
||||
|
||||
|
||||
def action_keyvault_del(keyvault_client, keyvault_uri, name):
|
||||
# type: (azure.keyvault.KeyVaultClient, str, str) -> None
|
||||
"""Action: Keyvault Del
|
||||
:param azure.keyvault.KeyVaultClient keyvault_client: keyvault client
|
||||
:param str keyvault_uri: keyvault uri
|
||||
:param str name: secret name
|
||||
"""
|
||||
keyvault.delete_secret(keyvault_client, keyvault_uri, name)
|
||||
|
||||
|
||||
def action_keyvault_list(keyvault_client, keyvault_uri):
|
||||
# type: (azure.keyvault.KeyVaultClient, str) -> None
|
||||
"""Action: Keyvault List
|
||||
:param azure.keyvault.KeyVaultClient keyvault_client: keyvault client
|
||||
:param str keyvault_uri: keyvault uri
|
||||
"""
|
||||
keyvault.list_secrets(keyvault_client, keyvault_uri)
|
||||
|
||||
|
||||
def action_cert_create(config):
|
||||
# type: (dict) -> None
|
||||
"""Action: Cert Create
|
||||
|
|
|
@ -34,9 +34,11 @@ import json
|
|||
import logging
|
||||
import zlib
|
||||
# non-stdlib imports
|
||||
import adal
|
||||
import azure.common.credentials
|
||||
import azure.keyvault
|
||||
import azure.mgmt.resource.resources
|
||||
import msrestazure.azure_active_directory
|
||||
# local imports
|
||||
from . import settings
|
||||
from . import util
|
||||
|
@ -52,8 +54,8 @@ _SECRET_ENCODED_FORMAT_VALUE = 'zlib+base64'
|
|||
|
||||
def _create_aad_credentials(
|
||||
aad_directory_id, aad_application_id, aad_auth_key, aad_user,
|
||||
aad_password):
|
||||
# type: (str, str, str, str, str) ->
|
||||
aad_password, aad_cert_private_key, aad_cert_thumbprint):
|
||||
# type: (str, str, str, str, str, str, str) ->
|
||||
# azure.common.credentials.ServicePrincipalCredentials or
|
||||
# azure.common.credentials.UserPassCredentials
|
||||
"""Create Azure Active Directory credentials
|
||||
|
@ -62,46 +64,67 @@ def _create_aad_credentials(
|
|||
:param str aad_auth_key: aad auth key
|
||||
:param str aad_user: aad user
|
||||
:param str aad_password: aad_password
|
||||
:param str aad_cert_private_key: path to rsa private key
|
||||
:param str aad_cert_thumbprint: sha1 thumbprint
|
||||
:rtype: azure.common.credentials.ServicePrincipalCredentials or
|
||||
azure.common.credentials.UserPassCredentials
|
||||
:return: aad credentials object
|
||||
"""
|
||||
if aad_directory_id is not None and aad_user is not None:
|
||||
raise ValueError(
|
||||
'cannot specify both an AAD Service Principal and User')
|
||||
if aad_directory_id is not None:
|
||||
if aad_application_id is not None and aad_cert_private_key is not None:
|
||||
if aad_auth_key is not None:
|
||||
raise ValueError('cannot specify both cert auth and auth key')
|
||||
if aad_password is not None:
|
||||
raise ValueError('cannot specify both cert auth and password')
|
||||
context = adal.AuthenticationContext(
|
||||
'https://login.microsoftonline.com/{}'.format(aad_directory_id))
|
||||
return msrestazure.azure_active_directory.AdalAuthentication(
|
||||
lambda: context.acquire_token_with_client_certificate(
|
||||
_KEYVAULT_RESOURCE,
|
||||
aad_application_id,
|
||||
util.decode_string(open(aad_cert_private_key, 'rb').read()),
|
||||
aad_cert_thumbprint
|
||||
)
|
||||
)
|
||||
elif aad_auth_key is not None:
|
||||
if aad_password is not None:
|
||||
raise ValueError(
|
||||
'cannot specify both an AAD Service Principal and User')
|
||||
return azure.common.credentials.ServicePrincipalCredentials(
|
||||
aad_application_id,
|
||||
aad_auth_key,
|
||||
tenant=aad_directory_id,
|
||||
resource=_KEYVAULT_RESOURCE,
|
||||
)
|
||||
elif aad_user is not None:
|
||||
elif aad_password is not None:
|
||||
return azure.common.credentials.UserPassCredentials(
|
||||
username=aad_user,
|
||||
password=aad_password,
|
||||
resource=_KEYVAULT_RESOURCE,
|
||||
)
|
||||
else:
|
||||
raise ValueError('neither AAD Service Principal or User specified')
|
||||
raise ValueError(
|
||||
'AAD Service Principal, User or Certificate not specified')
|
||||
|
||||
|
||||
def create_client(
|
||||
aad_directory_id, aad_application_id, aad_auth_key, aad_user,
|
||||
aad_password):
|
||||
# type: (str, str, str, str, str) -> azure.keyvault.KeyVaultClient
|
||||
aad_password, aad_cert_private_key, aad_cert_thumbprint):
|
||||
# type: (str, str, str, str, str, str, str) ->
|
||||
# azure.keyvault.KeyVaultClient
|
||||
"""Create KeyVault client
|
||||
:param str aad_directory_id: aad directory/tenant id
|
||||
:param str aad_application_id: aad application/client id
|
||||
:param str aad_auth_key: aad auth key
|
||||
:param str aad_user: aad user
|
||||
:param str aad_password: aad_password
|
||||
:param str aad_cert_private_key: path to rsa private key
|
||||
:param str aad_cert_thumbprint: sha1 thumbprint
|
||||
:rtype: azure.keyvault.KeyVaultClient
|
||||
:return: keyvault client
|
||||
"""
|
||||
credentials = _create_aad_credentials(
|
||||
aad_directory_id, aad_application_id, aad_auth_key, aad_user,
|
||||
aad_password)
|
||||
aad_password, aad_cert_private_key, aad_cert_thumbprint)
|
||||
return azure.keyvault.KeyVaultClient(credentials)
|
||||
|
||||
|
||||
|
@ -145,7 +168,9 @@ def store_credentials_json(client, config, keyvault_uri, secret_name):
|
|||
:param str keyvault_uri: keyvault uri
|
||||
:param str secret_name: secret name for creds json
|
||||
"""
|
||||
creds = {'credentials': settings.raw_credentials(config)}
|
||||
creds = {
|
||||
'credentials': settings.raw_credentials(config, True)
|
||||
}
|
||||
creds = json.dumps(creds).encode('utf8')
|
||||
# first zlib compress and encode as base64
|
||||
encoded = util.base64_encode_string(zlib.compress(creds))
|
||||
|
|
|
@ -146,6 +146,13 @@ ResourceFileSettings = collections.namedtuple(
|
|||
'file_path', 'blob_source', 'file_mode',
|
||||
]
|
||||
)
|
||||
KeyVaultSettings = collections.namedtuple(
|
||||
'KeyVaultSettings', [
|
||||
'keyvault_uri', 'keyvault_credentials_secret_id', 'aad_directory_id',
|
||||
'aad_application_id', 'aad_auth_key', 'aad_user', 'aad_password',
|
||||
'aad_cert_private_key', 'aad_cert_thumbprint',
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def get_gluster_volume():
|
||||
|
@ -480,14 +487,96 @@ def pool_sku(config, lower=False):
|
|||
|
||||
|
||||
# CREDENTIALS SETTINGS
|
||||
def raw_credentials(config):
|
||||
# type: (dict) -> dict
|
||||
def raw_credentials(config, omit_keyvault):
|
||||
# type: (dict, bool) -> dict
|
||||
"""Get raw credentials dictionary
|
||||
:param dict config: configuration object
|
||||
:param bool omit_keyvault: omit keyvault settings if present
|
||||
:rtype: dict
|
||||
:return: credentials dict
|
||||
"""
|
||||
return config['credentials']
|
||||
conf = config['credentials']
|
||||
if omit_keyvault:
|
||||
conf.pop('keyvault', None)
|
||||
return conf
|
||||
|
||||
|
||||
def credentials_keyvault(config):
|
||||
# type: (dict) -> KeyVaultSettings
|
||||
"""Get KeyVault settings
|
||||
:param dict config: configuration object
|
||||
:rtype: KeyVaultSettings
|
||||
:return: Key Vault settings
|
||||
"""
|
||||
try:
|
||||
conf = config['credentials']['keyvault']
|
||||
except (KeyError, TypeError):
|
||||
conf = {}
|
||||
try:
|
||||
keyvault_uri = conf['uri']
|
||||
if util.is_none_or_empty(keyvault_uri):
|
||||
raise KeyError()
|
||||
except KeyError:
|
||||
keyvault_uri = None
|
||||
try:
|
||||
keyvault_credentials_secret_id = conf['credentials_secret_id']
|
||||
if util.is_none_or_empty(keyvault_credentials_secret_id):
|
||||
raise KeyError()
|
||||
except KeyError:
|
||||
keyvault_credentials_secret_id = None
|
||||
try:
|
||||
aad_directory_id = conf['aad']['directory_id']
|
||||
if util.is_none_or_empty(aad_directory_id):
|
||||
raise KeyError()
|
||||
except KeyError:
|
||||
aad_directory_id = None
|
||||
try:
|
||||
aad_application_id = conf['aad']['application_id']
|
||||
if util.is_none_or_empty(aad_application_id):
|
||||
raise KeyError()
|
||||
except KeyError:
|
||||
aad_application_id = None
|
||||
try:
|
||||
aad_auth_key = conf['aad']['auth_key']
|
||||
if util.is_none_or_empty(aad_auth_key):
|
||||
raise KeyError()
|
||||
except KeyError:
|
||||
aad_auth_key = None
|
||||
try:
|
||||
aad_user = conf['aad']['user']
|
||||
if util.is_none_or_empty(aad_user):
|
||||
raise KeyError()
|
||||
except KeyError:
|
||||
aad_user = None
|
||||
try:
|
||||
aad_password = conf['aad']['password']
|
||||
if util.is_none_or_empty(aad_password):
|
||||
raise KeyError()
|
||||
except KeyError:
|
||||
aad_password = None
|
||||
try:
|
||||
aad_cert_private_key = conf['aad']['rsa_private_key_pem']
|
||||
if util.is_none_or_empty(aad_cert_private_key):
|
||||
raise KeyError()
|
||||
except KeyError:
|
||||
aad_cert_private_key = None
|
||||
try:
|
||||
aad_cert_thumbprint = conf['aad']['x509_cert_sha1_thumbprint']
|
||||
if util.is_none_or_empty(aad_cert_thumbprint):
|
||||
raise KeyError()
|
||||
except KeyError:
|
||||
aad_cert_thumbprint = None
|
||||
return KeyVaultSettings(
|
||||
keyvault_uri=keyvault_uri,
|
||||
keyvault_credentials_secret_id=keyvault_credentials_secret_id,
|
||||
aad_directory_id=aad_directory_id,
|
||||
aad_application_id=aad_application_id,
|
||||
aad_auth_key=aad_auth_key,
|
||||
aad_user=aad_user,
|
||||
aad_password=aad_password,
|
||||
aad_cert_private_key=aad_cert_private_key,
|
||||
aad_cert_thumbprint=aad_cert_thumbprint,
|
||||
)
|
||||
|
||||
|
||||
def credentials_batch(config):
|
||||
|
|
|
@ -29,6 +29,19 @@ The credentials schema is as follows:
|
|||
```json
|
||||
{
|
||||
"credentials": {
|
||||
"keyvault": {
|
||||
"uri": "https://myvault.vault.azure.net/",
|
||||
"credentials_secret_id": "https://myvault.vault.azure.net/secrets/credentialsjson",
|
||||
"aad": {
|
||||
"directory_id": "01234567-89ab-cdef-0123-456789abcdef",
|
||||
"application_id": "01234567-89ab-cdef-0123-456789abcdef",
|
||||
"auth_key": "01234...",
|
||||
"rsa_private_key_pem": "/path/to/privkey.pem",
|
||||
"x509_cert_sha1_thumbprint": "01AB02CD...",
|
||||
"user": "me@domain.com",
|
||||
"password": "password"
|
||||
}
|
||||
},
|
||||
"batch": {
|
||||
"account": "awesomebatchaccountname",
|
||||
"account_key": "batchaccountkey",
|
||||
|
@ -61,6 +74,31 @@ The credentials schema is as follows:
|
|||
|
||||
The `credentials` property is where Azure Batch and Storage credentials
|
||||
are defined.
|
||||
* (optional) The `keyvault` property defines the required members for
|
||||
accessing Azure KeyVault with Azure Active Directory credentials. Note that
|
||||
this property is *mutually exclusive* of all other properties in this file.
|
||||
If you need to define other members in this config file while using Azure
|
||||
KeyVault, then you will need to use environment variables or cli parameters
|
||||
instead for AAD and KeyVault credentials.
|
||||
* (optional) `uri` property defines the Azure KeyVault DNS name (URI).
|
||||
* (optional) `credentials_secret_id` property defines the KeyVault secret
|
||||
id containing an entire credentials.json file.
|
||||
* (optional) `aad` property contains members for Azure Active Directory
|
||||
credentials. Note that some options are mutually exclusive of each other
|
||||
depending upon authentication type: `auth_key`, `rsa_private_key_pem` and
|
||||
`password` cannot be defined at the same time. Please see the
|
||||
[Azure KeyVault and Batch Shipyard Guide](74-batch-shipyard-azure-keyvault.md)
|
||||
for more information. Note that any of the following can be specified as
|
||||
a CLI option or environment variable instead. For example, if you do not
|
||||
want to store the `auth_key` in the file, it can be specified at runtime.
|
||||
* (optional) `directory_id` AAD directory (tenant) id
|
||||
* (optional) `application_id` AAD application (client) id
|
||||
* (optional) `auth_key` Service Principal authentication key
|
||||
* (optional) `rsa_private_key_pem` path to RSA private key PEM file
|
||||
* (optional) `x509_cert_sha1_thumbprint` thumbprint of the X.509
|
||||
certificate for use with Certificate-based authentication
|
||||
* (optional) `user` AAD username
|
||||
* (optional) `password` AAD password associated with the user
|
||||
* (required) The `batch` property defines the Azure Batch account. Members
|
||||
under the `batch` property can be found in the
|
||||
[Azure Portal](https://portal.azure.com) under your Batch account.
|
||||
|
|
|
@ -30,7 +30,7 @@ is useful for managing sensitive data such as secrets.
|
|||
The following setup sections will guide you through setting up Azure
|
||||
Active Directory and KeyVault for use with Batch Shipyard.
|
||||
|
||||
### Azure Active Directory Setup
|
||||
### Azure Active Directory Setup with Service Principal Key-based Authentication
|
||||
If you will use your login for accessing your Azure subscription (e.g., your
|
||||
login to Azure Portal loads your subscription) as credentials to access your
|
||||
KeyVault in your subscription, then you can skip this section and proceed
|
||||
|
@ -38,17 +38,24 @@ to the Azure KeyVault Setup below. If not, or if you prefer to use an Active
|
|||
Directory Service Principal, then please continue following the directions
|
||||
below.
|
||||
|
||||
If you prefer to use asymmetric X.509 certificate-based authentication, then
|
||||
please see the next section. You can also augment the Key-based Authentication
|
||||
with Certificate authentication by following the Certificate guide immediately
|
||||
after the Key-based authentication guide.
|
||||
|
||||
#### Step 0: Get or Create a Directory
|
||||
First, you will need to create a directory if you do not have any existing
|
||||
directories (you should have a default directory) or if you are a user of a
|
||||
directory that does not allow you to register an Application. You will need
|
||||
to use the [Classic Azure Portal](https://manage.windowsazure.com/) to create
|
||||
a directory.
|
||||
a directory, however, it is recommended to use the default directory that
|
||||
is associated with your subscription if possible.
|
||||
|
||||
#### Step 1: Retrieve the Directory ID
|
||||
Retrieve the Directory ID of the Active Directory from the Azure Portal.
|
||||
Click on `Azure Active Directory` on the left menu and then `Properties`. You
|
||||
will see the `Directory ID` displayed on the next blade on the right.
|
||||
Retrieve the Directory ID of the Active Directory from the
|
||||
[Azure Portal](https://portal.azure.com). Click on `Azure Active Directory`
|
||||
on the left menu and then `Properties`. You will see the `Directory ID`
|
||||
displayed on the next blade on the right.
|
||||
|
||||
![74-aad-step1-0.png](https://azurebatchshipyard.blob.core.windows.net/github/74-aad-step1-0.png)
|
||||
|
||||
|
@ -67,13 +74,13 @@ the Create blade.
|
|||
|
||||
![74-aad-step2-0.png](https://azurebatchshipyard.blob.core.windows.net/github/74-aad-step2-0.png)
|
||||
|
||||
Ensure that the Application Type is set as `Native`. The `Redirect URI` does
|
||||
not have to exist, you can fill in anything you'd like here. Once completed,
|
||||
hit the Create button at the bottom.
|
||||
Ensure that the Application Type is set as `Web app / API`. The `Redirect URI`
|
||||
does not have to exist, you can fill in anything you'd like here. Once
|
||||
completed, hit the `Create` button at the bottom.
|
||||
|
||||
#### Step 3: Retrieve the Application ID
|
||||
Retrieve the `Application ID` for the application you just registered by
|
||||
refreshing the App registrations blade. You will see the `Application ID`
|
||||
refreshing the `App registrations` blade. You will see the `Application ID`
|
||||
on the top right of the blade.
|
||||
|
||||
![74-aad-step3-0.png](https://azurebatchshipyard.blob.core.windows.net/github/74-aad-step3-0.png)
|
||||
|
@ -94,9 +101,121 @@ blade (if not, click the `All settings ->` button). Click on `Keys` under
|
|||
|
||||
Add a description for the key and select an appropriate expiration interval.
|
||||
Click on the `Save` button at the top left of the blade. After you save
|
||||
the key, the key `VALUE` will be displayed. Copy this value. This is the
|
||||
argument to pass to the option `--aad-auth-key` or set as the environment
|
||||
variable `SHIPYARD_AAD_AUTH_KEY`.
|
||||
the key, the key `VALUE` will be displayed. Copy this value and ensure this
|
||||
value is stored somewhere safe. This is the argument to pass to the option
|
||||
`--aad-auth-key` or set as the environment variable `SHIPYARD_AAD_AUTH_KEY`.
|
||||
Once you navigate away from this blade, the value of the key cannot be
|
||||
retrieved again.
|
||||
|
||||
### Azure Active Directory Setup with Service Principal Certificate-based Authentication
|
||||
The following describes how to set up Azure Active Directory with asymmetric
|
||||
X.509 certificate-based authentication. The
|
||||
[Azure CLI](https://docs.microsoft.com/en-us/azure/xplat-cli-install) will
|
||||
be used in this guide to perform setup. Other tools such as Azure PowerShell
|
||||
can also be used.
|
||||
|
||||
#### Step 0: Login to Azure subscription and get Directory ID
|
||||
Log in to your Azure subscription with Azure cli:
|
||||
|
||||
```shell
|
||||
azure login
|
||||
azure account set "<subscription name or id>"
|
||||
```
|
||||
|
||||
Ensure that `azure` is running in ARM mode.
|
||||
|
||||
Retrieve the Directory ID with the following command:
|
||||
|
||||
```shell
|
||||
azure account show
|
||||
```
|
||||
|
||||
You will see a line starting with `Tenant ID`. This is the Directory ID.
|
||||
This is the argument to pass to the option `--aad-directory-id` or set as
|
||||
the environment variable `SHIPYARD_AAD_DIRECTORY_ID`.
|
||||
|
||||
#### Step 1: Create X.509 Certificate with Asymmetric Keys
|
||||
Execute the following `openssl` command, replacing the `-days` and
|
||||
`-subj` parameters with the appropriate values:
|
||||
|
||||
```shell
|
||||
openssl req -x509 -days 3650 -newkey rsa:2048 -out cert.pem -nodes -subj '/CN=mykeyvault'
|
||||
```
|
||||
|
||||
This command will create two files: `cert.pem` and `privkey.pem`. The
|
||||
`cert.pem` file contains the X.509 certificate with public key. This
|
||||
certificate will be attached to the Active Directory Application.
|
||||
|
||||
The `privkey.pem` file contains the RSA private key that will be used to
|
||||
authenticate with Azure Active Directory for the Service Principal. This
|
||||
file path is the argument to pass to the option `--aad-cert-private-key` or
|
||||
set as the environment variable `SHIPYARD_AAD_CERT_PRIVATE_KEY`.
|
||||
|
||||
You will also need to get the SHA1 thumbprint of the certificate created.
|
||||
This can be done with the following command:
|
||||
|
||||
```shell
|
||||
openssl x509 -in cert.pem -fingerprint -noout | sed 's/SHA1 Fingerprint=//g' | sed 's/://g'
|
||||
```
|
||||
|
||||
This value output is the argument to pass to the option
|
||||
`--aad-cert-thumbprint` or set as the environment variable
|
||||
`SHIPYARD_AAD_CERT_THUMBPRINT`.
|
||||
|
||||
#### Step 2: Create an Active Directory Application and Service Principal with Certificate
|
||||
Execute the following command to create the AAD application and Service
|
||||
Principal together with the Certificate data, replacing the `-n` value
|
||||
with the name of the application as desired:
|
||||
|
||||
```shell
|
||||
azure ad sp create -n mykeyvault --cert-value "$(tail -n+2 cert.pem | head -n-1 | tr -d '\n')"
|
||||
```
|
||||
|
||||
You can specify an optional `--end-date` parameter to change the validity
|
||||
period of the certificate.
|
||||
|
||||
This action will output something similar to the following:
|
||||
```
|
||||
data: Object Id: abcdef01-2345-6789-abcd-ef0123456789
|
||||
data: Display Name: mykeyvault
|
||||
data: Service Principal Names:
|
||||
data: 01234567-89ab-cdef-0123-456789abcdef
|
||||
data: http://mykeyvault
|
||||
```
|
||||
|
||||
Note the ID under `Service Prinipal Names:`. This is the Application ID.
|
||||
This is the argument to pass to the option `--aad-application-id` or set
|
||||
as the environment variable `SHIPYARD_AAD_APPLICATION_ID`.
|
||||
|
||||
#### Step 3: Create a Role for the Service Principal
|
||||
Execute the following command to create a role for the service principal.
|
||||
You will need the `Object Id` as displayed in the previous step and your
|
||||
Azure Subscription ID. Replace the `-o` role name with one of `Owner`,
|
||||
`Contributor`, or `Reader` (if this Service Principal will only read
|
||||
from KeyVault).
|
||||
|
||||
```shell
|
||||
azure role assignment create --objectId abcdef01-2345-6789-abcd-ef0123456789 -o Contributor -c /subscriptions/11111111-2222-3333-4444-555555555555/
|
||||
```
|
||||
|
||||
You should receive a message output that the role assignment has been
|
||||
completed successfully.
|
||||
|
||||
You can now assign this Service Principal with Certificate-based
|
||||
authentication to an Azure KeyVault as per instructions below.
|
||||
|
||||
#### [Optional] Set Certificate Data for Existing Service Principal
|
||||
If you followed the prior section for creating a Service Principal with
|
||||
Key-based authentication, you can augment the Service Principal with
|
||||
Certificate-based authentication by executing the following command,
|
||||
replacing the `-o` parameter with the Object Id of the AAD Application:
|
||||
|
||||
```shell
|
||||
azure ad app set -o abcdef01-2345-6789-abcd-ef0123456789 --cert-value "$(tail -n+2 cert.pem | head -n-1 | tr -d '\n')"
|
||||
```
|
||||
|
||||
You can specify an optional `--end-date` parameter to change the validity
|
||||
period of the certificate.
|
||||
|
||||
### Azure KeyVault Setup
|
||||
The following describes how to set up a new KeyVault for use with Batch
|
||||
|
@ -116,7 +235,7 @@ the blade that follows.
|
|||
|
||||
![74-akv-step0-1.png](https://azurebatchshipyard.blob.core.windows.net/github/74-akv-step0-1.png)
|
||||
|
||||
#### Step 1: Create KeyVault
|
||||
#### Step 1: Create the KeyVault
|
||||
In the Create Key Vault blade, fill in the `Name`, select the `Subscription`
|
||||
to use, set the `Resource Group` and `Location` of the KeyVault to be created.
|
||||
|
||||
|
@ -127,12 +246,12 @@ Service Principal, then skip to the next step, but follow the instructions for
|
|||
the specific Active Directory User. If you are using an Active Directory
|
||||
Service Principal, then hit the `Add new` button, then `Select principal`. In
|
||||
the next blade, type the name of the Application added in the prior section
|
||||
to Active Directory. Select this application by clicking on it and the Select
|
||||
button on the bottom of the blade.
|
||||
to Active Directory. Select this application by clicking on it and the
|
||||
`Select` button on the bottom of the blade.
|
||||
|
||||
#### Step 2: Set Secret Permissions
|
||||
From the `Configure from template (optional)` pulldown, select either
|
||||
`Key & Secret Management` or `Secret Management`, then hit OK.
|
||||
`Key & Secret Management` or `Secret Management`, then click the `OK` button.
|
||||
|
||||
![74-akv-step2-0.png](https://azurebatchshipyard.blob.core.windows.net/github/74-akv-step2-0.png)
|
||||
|
||||
|
@ -155,10 +274,27 @@ with Batch Shipyard with Azure KeyVault using Azure Active Directory
|
|||
credentials.
|
||||
|
||||
### Authenticating with AAD and Azure KeyVault
|
||||
You will need to provide *either* an AAD Service Principal or AAD
|
||||
User/Password to authenticate for access to your KeyVault. These options
|
||||
are mutually exclusive. For an AAD Service Principal, you would need to
|
||||
provide the following options to your `shipyard` invocation:
|
||||
You will need to provide one of the following:
|
||||
|
||||
1. an AAD Service Principal with an authentication key
|
||||
2. an AAD Service Principal with a RSA private key and X.509 certificate
|
||||
thumbprint
|
||||
3. an AAD User/Password
|
||||
|
||||
in order to authenticate for access to your KeyVault. These options
|
||||
are mutually exclusive.
|
||||
|
||||
You can either provide the required parameters through CLI options,
|
||||
environment variables, or the `credentials.json` file.
|
||||
|
||||
Please see the [configuration guide](10-batch-shipyard-configuration.md) for
|
||||
the appropriate json properties to populate that correlate with the following
|
||||
options below. Note that the `keyvault add` command must use a
|
||||
`credentials.json` file that does not have KeyVault and AAD credentials.
|
||||
For this command, you will need to use CLI options or environment variables.
|
||||
|
||||
For an AAD Service Principal with Key-based authentication, you will need
|
||||
to provide the following options to your `shipyard` invocation:
|
||||
|
||||
```
|
||||
--aad-directory-id <DIRECTORY-ID> --aad-application-id <APPLICATION-ID> --aad-auth-key <AUTH-KEY>
|
||||
|
@ -170,6 +306,27 @@ or as environment variables:
|
|||
SHIPYARD_AAD_DIRECTORY_ID=<DIRECTORY-ID> SHIPYARD_AAD_APPLICATION_ID=<APPLICATION-ID> SHIPYARD_AAD_AUTH_KEY=<AUTH-KEY>
|
||||
```
|
||||
|
||||
For an AAD Service Principal with Certificate-based authentication, you will
|
||||
need to provide the following options to your `shipyard` invocation:
|
||||
|
||||
```
|
||||
--aad-directory-id <DIRECTORY-ID> --aad-application-id <APPLICATION-ID> --aad-cert-private-key <RSA-PRIVATE-KEY-FILE> --aad-cert-thumbprint <CERT-SHA1-THUMBPRINT>
|
||||
```
|
||||
|
||||
or as environment variables:
|
||||
|
||||
```
|
||||
SHIPYARD_AAD_DIRECTORY_ID=<DIRECTORY-ID> SHIPYARD_AAD_APPLICATION_ID=<APPLICATION-ID> SHIPYARD_AAD_CERT_PRIVATE_KEY=<RSA-PRIVATE-KEY-FILE> SHIPYARD_AAD_CERT_THUMBPRINT=<CERT-SHA1-THUMBPRINT>
|
||||
```
|
||||
|
||||
To retrieve the SHA1 thumbprint for the X.509 certificate (not the RSA
|
||||
private key) associated with your Service Principal, you can run the
|
||||
following `openssl` command against your certificate file:
|
||||
|
||||
```shell
|
||||
openssl x509 -in cert.pem -fingerprint -noout | sed 's/SHA1 Fingerprint=//g' | sed 's/://g'
|
||||
```
|
||||
|
||||
To use an AAD User/Password to authenticate for access to your KeyVault, you
|
||||
would need to add the following options to your `shipyard` invocation.
|
||||
|
||||
|
@ -203,11 +360,16 @@ it is recommended to use the Batch Shipyard CLI to store your
|
|||
and can allow for potentially very large credential files as compression
|
||||
is applied to the file prior to placing the secret in KeyVault. To create
|
||||
a credentials secret, pass all of the required AAD and KeyVault URI options
|
||||
to `keyvault add`. For example:
|
||||
to `keyvault add`. Note that you cannot use AAD/KeyVault credential options
|
||||
in a `credentials.json` file to authenticate with KeyVault to store the
|
||||
same json file. You must use CLI options or environment variables to pass
|
||||
the appropriate Azure Keyvault and AAD credentials to `shipyard` for this
|
||||
command. For example:
|
||||
|
||||
```shell
|
||||
# add the appropriate AAD and KeyVault URI options or environment variables
|
||||
# to the below invocation
|
||||
# to the below invocation. These AAD/KeyVault authentication options cannot
|
||||
# be present in credentials.json.
|
||||
shipyard keyvault add mycreds --credentials credentials.json
|
||||
```
|
||||
|
||||
|
@ -228,7 +390,9 @@ https://myvault.vault.azure.net/secrets/mycreds
|
|||
```
|
||||
|
||||
This secret id is required for retrieving your `credentials.json` contents
|
||||
for latter invocations that require valid credentials to use Batch Shipyard.
|
||||
for later invocations that require these particular credentials to interact
|
||||
with Batch Shipyard. How to pass this secret id will be explained in the next
|
||||
section.
|
||||
|
||||
You can also store individual keys as secrets in your KeyVault and reference
|
||||
them within your `credentials.json` file. For example:
|
||||
|
@ -249,20 +413,23 @@ options to the invocation and then populate the `account_key` property from
|
|||
the value of the secret.
|
||||
|
||||
These `*_keyvault_secret_id` properties can be used in lieu of batch account
|
||||
keys, storage account keys, and private docker registry passwords. Please
|
||||
see the [configuration guide](10-batch-shipyard-configuration.md) for more
|
||||
keys, storage account keys, and private Docker Registry passwords. You will
|
||||
need to populate the associated KeyVault with these secrets manually and
|
||||
set the json properties in the `credentials.json` file with the corresponding
|
||||
secret ids. Please see the
|
||||
[configuration guide](10-batch-shipyard-configuration.md) for more
|
||||
information.
|
||||
|
||||
Finally, Batch Shipyard does support nested KeyVault secrets. In other words,
|
||||
the `credentials.json` file can be a secret in KeyVault and there can be
|
||||
`*_keyvault_secret_id` properties within the json file stored in KeyVault
|
||||
which will then be fetched.
|
||||
which subsequently will be fetched automatically.
|
||||
|
||||
### Fetching Credentials from KeyVault
|
||||
To specify a `credentials.json` as a secret in KeyVault, you can omit the
|
||||
`--credentials` option (or specify a `--configdir` option without a
|
||||
`credentials.json` file in the path pointed to by `--configdir`) and instead
|
||||
specify the option:
|
||||
`credentials.json` file on disk in the path pointed to by `--configdir`) and
|
||||
instead specify the option:
|
||||
|
||||
```
|
||||
--keyvault-credentials-secret-id <SECRET-ID>
|
||||
|
@ -274,14 +441,29 @@ SHIPYARD_KEYVAULT_CREDENTIALS_SECRET_ID=<SECRET-ID>
|
|||
```
|
||||
|
||||
If you have a physical `credentials.json` file on disk, but with
|
||||
`*_keyvault_secret_id` properties then you do not need to specify the above
|
||||
`*_keyvault_secret_id` properties then you must not specify the above
|
||||
option as Batch Shipyard will parse the credentials file and perform
|
||||
the lookup and secret retrieval.
|
||||
the lookup and secret retrieval automatically.
|
||||
|
||||
## Configuration Documentation
|
||||
Please see [this page](10-batch-shipyard-configuration.md) for a full
|
||||
explanation of each configuration option.
|
||||
## More Documentation
|
||||
You can perform many Azure Active Directory setup steps through the Azure CLI.
|
||||
This [document](https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-authenticate-service-principal-cli)
|
||||
explains how to create a Service Principal among other topics. To create
|
||||
an Azure KeyVault with the Azure CLI, this
|
||||
[document](https://docs.microsoft.com/en-us/azure/key-vault/key-vault-manage-with-cli#register-an-application-with-azure-active-directory)
|
||||
explains the steps involved. Additionally, it shows how to authorize an AAD
|
||||
Application for use with KeyVault.
|
||||
|
||||
## Usage Documentation
|
||||
Please see [this page](20-batch-shipyard-usage.md) for a full
|
||||
Securing your KeyVault can be handled through the Azure Portal or through
|
||||
the Azure CLI. This
|
||||
[document](https://docs.microsoft.com/en-us/azure/key-vault/key-vault-secure-your-key-vault)
|
||||
explains concepts and how to secure your KeyVault. A general overview of
|
||||
Role-Based Access Control (RBAC) and how to manage access to various
|
||||
resources can be found in this
|
||||
[document](https://docs.microsoft.com/en-us/azure/active-directory/role-based-access-control-what-is).
|
||||
|
||||
For further Batch Shipyard documentation, please see
|
||||
[this page](10-batch-shipyard-configuration.md) for a full
|
||||
explanation of each property in the configuration files. Please see
|
||||
[this page](20-batch-shipyard-usage.md) for a full
|
||||
explanation of all commands and options for `shipyard`.
|
||||
|
|
|
@ -13,6 +13,8 @@ current limitation of the underlying Azure Batch service.
|
|||
This is a current limitation of the underlying VM and host drivers.
|
||||
* On-premise Docker private registries are not supported at this time due to
|
||||
VNet requirements.
|
||||
* Credential storage using Azure Active Directory and KeyVault is only
|
||||
supported for Azure Public Cloud regions.
|
||||
|
||||
The following Azure Batch actions should only be performed through Batch
|
||||
Shipyard when deploying your workload through this toolkit, as Batch
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
adal==0.4.3
|
||||
azure-batch==1.1.0
|
||||
azure-keyvault==0.1.0
|
||||
azure-storage==0.33.0
|
||||
blobxfer==0.12.1
|
||||
click==6.6
|
||||
future==0.16.0
|
||||
msrestazure==0.4.6
|
||||
pathlib2==2.1.0; python_version < '3.5'
|
||||
scandir==1.4; python_version < '3.5'
|
||||
|
|
107
shipyard.py
107
shipyard.py
|
@ -39,8 +39,8 @@ except ImportError:
|
|||
# non-stdlib imports
|
||||
import click
|
||||
# local imports
|
||||
import convoy.keyvault
|
||||
import convoy.fleet
|
||||
import convoy.settings
|
||||
import convoy.util
|
||||
|
||||
# create logger
|
||||
|
@ -69,6 +69,8 @@ class CliContext(object):
|
|||
self.aad_auth_key = None
|
||||
self.aad_user = None
|
||||
self.aad_password = None
|
||||
self.aad_cert_private_key = None
|
||||
self.add_cert_thumbprint = None
|
||||
|
||||
def initialize(self, creds_only=False, no_config=False):
|
||||
# type: (CliContext, bool, bool) -> None
|
||||
|
@ -77,17 +79,20 @@ class CliContext(object):
|
|||
:param bool creds_only: credentials only initialization
|
||||
:param bool no_config: do not configure context
|
||||
"""
|
||||
self.keyvault_client = convoy.keyvault.create_client(
|
||||
self.aad_directory_id, self.aad_application_id,
|
||||
self.aad_auth_key, self.aad_user, self.aad_password)
|
||||
self._read_credentials_config()
|
||||
self.keyvault_client = convoy.fleet.create_keyvault_client(
|
||||
self, self.config)
|
||||
del self.aad_directory_id
|
||||
del self.aad_application_id
|
||||
del self.aad_auth_key
|
||||
del self.aad_user
|
||||
del self.aad_password
|
||||
del self.aad_cert_private_key
|
||||
del self.aad_cert_thumbprint
|
||||
self.config = None
|
||||
self._init_config(creds_only)
|
||||
if no_config:
|
||||
return
|
||||
self._init_config(creds_only)
|
||||
if not creds_only:
|
||||
clients = convoy.fleet.initialize(self.config)
|
||||
self._set_clients(*clients)
|
||||
|
@ -112,6 +117,21 @@ class CliContext(object):
|
|||
'is valid and is encoded UTF-8 without BOM.'.format(
|
||||
json_file)))
|
||||
|
||||
def _read_credentials_config(self):
|
||||
# type: (CliContext) -> None
|
||||
"""Read credentials config file only
|
||||
:param CliContext self: this
|
||||
"""
|
||||
# use configdir if available
|
||||
if self.configdir is not None and self.json_credentials is None:
|
||||
self.json_credentials = pathlib.Path(
|
||||
self.configdir, 'credentials.json')
|
||||
if (self.json_credentials is not None and
|
||||
not isinstance(self.json_credentials, pathlib.Path)):
|
||||
self.json_credentials = pathlib.Path(self.json_credentials)
|
||||
if self.json_credentials.exists():
|
||||
self._read_json_file(self.json_credentials)
|
||||
|
||||
def _init_config(self, creds_only=False):
|
||||
# type: (CliContext, bool) -> None
|
||||
"""Initializes configuration of the context
|
||||
|
@ -134,15 +154,6 @@ class CliContext(object):
|
|||
if (self.json_credentials is not None and
|
||||
not isinstance(self.json_credentials, pathlib.Path)):
|
||||
self.json_credentials = pathlib.Path(self.json_credentials)
|
||||
kvcreds = None
|
||||
if self.json_credentials is None or not self.json_credentials.exists():
|
||||
if self.keyvault_uri is None:
|
||||
raise ValueError('credentials json was not specified')
|
||||
else:
|
||||
# fetch credentials from keyvault
|
||||
kvcreds = convoy.keyvault.fetch_credentials_json(
|
||||
self.keyvault_client, self.keyvault_uri,
|
||||
self.keyvault_credentials_secret_id)
|
||||
if not creds_only:
|
||||
if self.json_config is None:
|
||||
raise ValueError('config json was not specified')
|
||||
|
@ -152,14 +163,40 @@ class CliContext(object):
|
|||
raise ValueError('pool json was not specified')
|
||||
elif not isinstance(self.json_pool, pathlib.Path):
|
||||
self.json_pool = pathlib.Path(self.json_pool)
|
||||
# load json files into memory
|
||||
# fetch credentials from keyvault, if json file is missing
|
||||
kvcreds = None
|
||||
if self.json_credentials is None or not self.json_credentials.exists():
|
||||
kvcreds = convoy.fleet.fetch_credentials_json_from_keyvault(
|
||||
self.keyvault_client, self.keyvault_uri,
|
||||
self.keyvault_credentials_secret_id)
|
||||
# read credentials json, perform special keyvault processing if
|
||||
# required sections are missing
|
||||
if kvcreds is None:
|
||||
self._read_json_file(self.json_credentials)
|
||||
kv = convoy.settings.credentials_keyvault(self.config)
|
||||
self.keyvault_uri = self.keyvault_uri or kv.keyvault_uri
|
||||
self.keyvault_credentials_secret_id = (
|
||||
self.keyvault_credentials_secret_id or
|
||||
kv.keyvault_credentials_secret_id
|
||||
)
|
||||
try:
|
||||
convoy.settings.credentials_batch(self.config)
|
||||
if len(list(convoy.settings.iterate_storage_credentials(
|
||||
self.config))) == 0:
|
||||
raise KeyError()
|
||||
except KeyError:
|
||||
# fetch credentials from keyvault
|
||||
self.config = \
|
||||
convoy.fleet.fetch_credentials_json_from_keyvault(
|
||||
self.keyvault_client, self.keyvault_uri,
|
||||
self.keyvault_credentials_secret_id)
|
||||
else:
|
||||
self.config = kvcreds
|
||||
del kvcreds
|
||||
del self.keyvault_credentials_secret_id
|
||||
# parse any keyvault secret ids from credentials
|
||||
convoy.keyvault.parse_secret_ids(self.keyvault_client, self.config)
|
||||
convoy.fleet.fetch_secrets_from_keyvault(
|
||||
self.keyvault_client, self.config)
|
||||
# read rest of config files
|
||||
if not creds_only:
|
||||
self._read_json_file(self.json_config)
|
||||
|
@ -312,6 +349,32 @@ def _aad_password_option(f):
|
|||
callback=callback)(f)
|
||||
|
||||
|
||||
def _aad_cert_private_key_option(f):
|
||||
def callback(ctx, param, value):
|
||||
clictx = ctx.ensure_object(CliContext)
|
||||
clictx.aad_cert_private_key = value
|
||||
return value
|
||||
return click.option(
|
||||
'--aad-cert-private-key',
|
||||
expose_value=False,
|
||||
envvar='SHIPYARD_AAD_CERT_PRIVATE_KEY',
|
||||
help='Azure Active Directory private key certificate',
|
||||
callback=callback)(f)
|
||||
|
||||
|
||||
def _aad_cert_thumbprint_option(f):
|
||||
def callback(ctx, param, value):
|
||||
clictx = ctx.ensure_object(CliContext)
|
||||
clictx.aad_cert_thumbprint = value
|
||||
return value
|
||||
return click.option(
|
||||
'--aad-cert-thumbprint',
|
||||
expose_value=False,
|
||||
envvar='SHIPYARD_AAD_CERT_THUMBPRINT',
|
||||
help='Azure Active Directory certificate SHA1 thumbprint',
|
||||
callback=callback)(f)
|
||||
|
||||
|
||||
def _configdir_option(f):
|
||||
def callback(ctx, param, value):
|
||||
clictx = ctx.ensure_object(CliContext)
|
||||
|
@ -381,6 +444,8 @@ def _jobs_option(f):
|
|||
|
||||
|
||||
def common_options(f):
|
||||
f = _aad_cert_thumbprint_option(f)
|
||||
f = _aad_cert_private_key_option(f)
|
||||
f = _aad_password_option(f)
|
||||
f = _aad_user_option(f)
|
||||
f = _aad_auth_key_option(f)
|
||||
|
@ -447,7 +512,7 @@ def keyvault(ctx):
|
|||
def keyvault_add(ctx, name):
|
||||
"""Add a credentials json as a secret to Azure KeyVault"""
|
||||
ctx.initialize(creds_only=True)
|
||||
convoy.keyvault.store_credentials_json(
|
||||
convoy.fleet.action_keyvault_add(
|
||||
ctx.keyvault_client, ctx.config, ctx.keyvault_uri, name)
|
||||
|
||||
|
||||
|
@ -457,8 +522,8 @@ def keyvault_add(ctx, name):
|
|||
@pass_cli_context
|
||||
def keyvault_del(ctx, name):
|
||||
"""Delete a secret from Azure KeyVault"""
|
||||
ctx.initialize(no_config=True)
|
||||
convoy.keyvault.delete_secret(
|
||||
ctx.initialize(creds_only=True, no_config=True)
|
||||
convoy.fleet.action_keyvault_del(
|
||||
ctx.keyvault_client, ctx.keyvault_uri, name)
|
||||
|
||||
|
||||
|
@ -467,8 +532,8 @@ def keyvault_del(ctx, name):
|
|||
@pass_cli_context
|
||||
def keyvault_list(ctx):
|
||||
"""List secret ids and metadata in an Azure KeyVault"""
|
||||
ctx.initialize(no_config=True)
|
||||
convoy.keyvault.list_secrets(ctx.keyvault_client, ctx.keyvault_uri)
|
||||
ctx.initialize(creds_only=True, no_config=True)
|
||||
convoy.fleet.action_keyvault_list(ctx.keyvault_client, ctx.keyvault_uri)
|
||||
|
||||
|
||||
@cli.group()
|
||||
|
|
Загрузка…
Ссылка в новой задаче