Merge pull request #1234 from dod-ccpo/kv-flask-config
Use Key Vault for Flask application config
This commit is contained in:
commit
d9c79b9b58
@ -3,7 +3,7 @@
|
|||||||
"files": "^.secrets.baseline$|^.*pgsslrootcert.yml$",
|
"files": "^.secrets.baseline$|^.*pgsslrootcert.yml$",
|
||||||
"lines": null
|
"lines": null
|
||||||
},
|
},
|
||||||
"generated_at": "2019-12-03T19:44:47Z",
|
"generated_at": "2019-12-05T17:54:05Z",
|
||||||
"plugins_used": [
|
"plugins_used": [
|
||||||
{
|
{
|
||||||
"base64_limit": 4.5,
|
"base64_limit": 4.5,
|
||||||
@ -98,7 +98,7 @@
|
|||||||
"hashed_secret": "afc848c316af1a89d49826c5ae9d00ed769415f3",
|
"hashed_secret": "afc848c316af1a89d49826c5ae9d00ed769415f3",
|
||||||
"is_secret": false,
|
"is_secret": false,
|
||||||
"is_verified": false,
|
"is_verified": false,
|
||||||
"line_number": 21,
|
"line_number": 29,
|
||||||
"type": "Secret Keyword"
|
"type": "Secret Keyword"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
17
README.md
17
README.md
@ -168,12 +168,7 @@ Testing file uploads and downloads locally requires a few configuration options.
|
|||||||
In the flask config (`config/base.ini`, perhaps):
|
In the flask config (`config/base.ini`, perhaps):
|
||||||
|
|
||||||
```
|
```
|
||||||
CSP=<aws | azure | mock>
|
CSP=< azure | mock>
|
||||||
|
|
||||||
AWS_REGION_NAME=""
|
|
||||||
AWS_ACCESS_KEY=""
|
|
||||||
AWS_SECRET_KEY=""
|
|
||||||
AWS_BUCKET_NAME=""
|
|
||||||
|
|
||||||
AZURE_STORAGE_KEY=""
|
AZURE_STORAGE_KEY=""
|
||||||
AZURE_ACCOUNT_NAME=""
|
AZURE_ACCOUNT_NAME=""
|
||||||
@ -183,7 +178,7 @@ AZURE_TO_BUCKET_NAME=""
|
|||||||
There are also some build-time configuration that are used by parcel. Add these to `.env.local`, and run `rm -r .cache/` before running `yarn build`:
|
There are also some build-time configuration that are used by parcel. Add these to `.env.local`, and run `rm -r .cache/` before running `yarn build`:
|
||||||
|
|
||||||
```
|
```
|
||||||
CLOUD_PROVIDER=<aws | azure | mock>
|
CLOUD_PROVIDER=<azure | mock>
|
||||||
AZURE_ACCOUNT_NAME=""
|
AZURE_ACCOUNT_NAME=""
|
||||||
AZURE_CONTAINER_NAME=""
|
AZURE_CONTAINER_NAME=""
|
||||||
```
|
```
|
||||||
@ -223,6 +218,9 @@ To generate coverage reports for the Javascript tests:
|
|||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
- `ASSETS_URL`: URL to host which serves static assets (such as a CDN).
|
- `ASSETS_URL`: URL to host which serves static assets (such as a CDN).
|
||||||
|
- `AZURE_ACCOUNT_NAME`: The name for the Azure blob storage account
|
||||||
|
- `AZURE_STORAGE_KEY`: A valid secret key for the Azure blob storage account
|
||||||
|
- `AZURE_TO_BUCKET_NAME`: The Azure blob storage container name for task order uploads
|
||||||
- `BLOB_STORAGE_URL`: URL to Azure blob storage container.
|
- `BLOB_STORAGE_URL`: URL to Azure blob storage container.
|
||||||
- `CAC_URL`: URL for the CAC authentication route.
|
- `CAC_URL`: URL for the CAC authentication route.
|
||||||
- `CA_CHAIN`: Path to the CA chain file.
|
- `CA_CHAIN`: Path to the CA chain file.
|
||||||
@ -238,6 +236,11 @@ To generate coverage reports for the Javascript tests:
|
|||||||
- `ENVIRONMENT`: String specifying the current environment. Acceptable values: "dev", "prod".
|
- `ENVIRONMENT`: String specifying the current environment. Acceptable values: "dev", "prod".
|
||||||
- `LIMIT_CONCURRENT_SESSIONS`: Boolean specifying if users should be allowed only one active session at a time.
|
- `LIMIT_CONCURRENT_SESSIONS`: Boolean specifying if users should be allowed only one active session at a time.
|
||||||
- `LOG_JSON`: Boolean specifying whether app should log in a json format.
|
- `LOG_JSON`: Boolean specifying whether app should log in a json format.
|
||||||
|
- `MAIL_PASSWORD`: String. Password for the SMTP server.
|
||||||
|
- `MAIL_PORT`: Integer. Port to use on the SMTP server.
|
||||||
|
- `MAIL_SENDER`: String. Email address to send outgoing mail from.
|
||||||
|
- `MAIL_SERVER`: The SMTP host
|
||||||
|
- `MAIL_TLS`: Boolean. Use TLS to connect to the SMTP server.
|
||||||
- `PERMANENT_SESSION_LIFETIME`: Integer specifying how many seconds a user's session can stay valid for. https://flask.palletsprojects.com/en/1.1.x/config/#PERMANENT_SESSION_LIFETIME
|
- `PERMANENT_SESSION_LIFETIME`: Integer specifying how many seconds a user's session can stay valid for. https://flask.palletsprojects.com/en/1.1.x/config/#PERMANENT_SESSION_LIFETIME
|
||||||
- `PGDATABASE`: String specifying the name of the postgres database.
|
- `PGDATABASE`: String specifying the name of the postgres database.
|
||||||
- `PGHOST`: String specifying the hostname of the postgres database.
|
- `PGHOST`: String specifying the hostname of the postgres database.
|
||||||
|
42
atst/app.py
42
atst/app.py
@ -200,23 +200,21 @@ def make_config(direct_config=None):
|
|||||||
ENV_CONFIG_FILENAME = os.path.join(
|
ENV_CONFIG_FILENAME = os.path.join(
|
||||||
os.path.dirname(__file__), "../config/", "{}.ini".format(ENV.lower())
|
os.path.dirname(__file__), "../config/", "{}.ini".format(ENV.lower())
|
||||||
)
|
)
|
||||||
OVERRIDE_CONFIG_FILENAME = os.getenv("OVERRIDE_CONFIG_FULLPATH")
|
OVERRIDE_CONFIG_DIRECTORY = os.getenv("OVERRIDE_CONFIG_DIRECTORY")
|
||||||
|
|
||||||
config = ConfigParser(allow_no_value=True)
|
config = ConfigParser(allow_no_value=True)
|
||||||
config.optionxform = str
|
config.optionxform = str
|
||||||
|
|
||||||
config_files = [BASE_CONFIG_FILENAME, ENV_CONFIG_FILENAME]
|
config_files = [BASE_CONFIG_FILENAME, ENV_CONFIG_FILENAME]
|
||||||
if OVERRIDE_CONFIG_FILENAME:
|
|
||||||
config_files.append(OVERRIDE_CONFIG_FILENAME)
|
|
||||||
|
|
||||||
# ENV_CONFIG will override values in BASE_CONFIG.
|
# ENV_CONFIG will override values in BASE_CONFIG.
|
||||||
config.read(config_files)
|
config.read(config_files)
|
||||||
|
|
||||||
|
if OVERRIDE_CONFIG_DIRECTORY:
|
||||||
|
apply_config_from_directory(OVERRIDE_CONFIG_DIRECTORY, config)
|
||||||
|
|
||||||
# Check for ENV variables as a final source of overrides
|
# Check for ENV variables as a final source of overrides
|
||||||
for confsetting in config.options("default"):
|
apply_config_from_environment(config)
|
||||||
env_override = os.getenv(confsetting.upper())
|
|
||||||
if env_override:
|
|
||||||
config.set("default", confsetting, env_override)
|
|
||||||
|
|
||||||
# override if a dictionary of options has been given
|
# override if a dictionary of options has been given
|
||||||
if direct_config:
|
if direct_config:
|
||||||
@ -244,6 +242,36 @@ def make_config(direct_config=None):
|
|||||||
return map_config(config)
|
return map_config(config)
|
||||||
|
|
||||||
|
|
||||||
|
def apply_config_from_directory(config_dir, config, section="default"):
|
||||||
|
"""
|
||||||
|
Loop files in a directory, check if the names correspond to
|
||||||
|
known config values, and apply the file contents as the value
|
||||||
|
for that setting if they do.
|
||||||
|
"""
|
||||||
|
for confsetting in os.listdir(config_dir):
|
||||||
|
if confsetting in config.options(section):
|
||||||
|
full_path = os.path.join(config_dir, confsetting)
|
||||||
|
with open(full_path, "r") as conf_file:
|
||||||
|
config.set(section, confsetting, conf_file.read().strip())
|
||||||
|
|
||||||
|
return config
|
||||||
|
|
||||||
|
|
||||||
|
def apply_config_from_environment(config, section="default"):
|
||||||
|
"""
|
||||||
|
Loops all the configuration settins in a given section of a
|
||||||
|
config object and checks whether those settings also exist as
|
||||||
|
environment variables. If so, it applies the environment
|
||||||
|
variables value as the new configuration setting value.
|
||||||
|
"""
|
||||||
|
for confsetting in config.options(section):
|
||||||
|
env_override = os.getenv(confsetting.upper())
|
||||||
|
if env_override:
|
||||||
|
config.set(section, confsetting, env_override)
|
||||||
|
|
||||||
|
return config
|
||||||
|
|
||||||
|
|
||||||
def make_redis(app, config):
|
def make_redis(app, config):
|
||||||
r = redis.Redis.from_url(config["REDIS_URI"])
|
r = redis.Redis.from_url(config["REDIS_URI"])
|
||||||
app.redis = r
|
app.redis = r
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
[default]
|
[default]
|
||||||
ASSETS_URL
|
ASSETS_URL
|
||||||
|
AZURE_ACCOUNT_NAME
|
||||||
|
AZURE_STORAGE_KEY
|
||||||
|
AZURE_TO_BUCKET_NAME
|
||||||
BLOB_STORAGE_URL=http://localhost:8000/
|
BLOB_STORAGE_URL=http://localhost:8000/
|
||||||
CAC_URL = http://localhost:8000/login-redirect
|
CAC_URL = http://localhost:8000/login-redirect
|
||||||
CA_CHAIN = ssl/server-certs/ca-chain.pem
|
CA_CHAIN = ssl/server-certs/ca-chain.pem
|
||||||
@ -15,6 +18,11 @@ DISABLE_CRL_CHECK = false
|
|||||||
ENVIRONMENT = dev
|
ENVIRONMENT = dev
|
||||||
LIMIT_CONCURRENT_SESSIONS = false
|
LIMIT_CONCURRENT_SESSIONS = false
|
||||||
LOG_JSON = false
|
LOG_JSON = false
|
||||||
|
MAIL_PASSWORD
|
||||||
|
MAIL_PORT
|
||||||
|
MAIL_SENDER
|
||||||
|
MAIL_SERVER
|
||||||
|
MAIL_TLS
|
||||||
PERMANENT_SESSION_LIFETIME = 1800
|
PERMANENT_SESSION_LIFETIME = 1800
|
||||||
PGDATABASE = atat
|
PGDATABASE = atat
|
||||||
PGHOST = localhost
|
PGHOST = localhost
|
||||||
|
@ -37,35 +37,6 @@ If you are satisfied with the output from the diff, you can apply the new config
|
|||||||
|
|
||||||
## Secrets and Configuration
|
## Secrets and Configuration
|
||||||
|
|
||||||
### atst-overrides.ini
|
|
||||||
|
|
||||||
Production configuration values are provided to the ATAT Flask app by writing an `atst-overrides.ini` file to the running Docker container. This file is stored as a Kubernetes secret. It contains configuration information for the database connection, mailer, etc.
|
|
||||||
|
|
||||||
To update the configuration, you can do the following:
|
|
||||||
|
|
||||||
```
|
|
||||||
kubectl -n atat get secret atst-config-ini -o=jsonpath='{.data.override\.ini}' | base64 --decode > override.ini
|
|
||||||
```
|
|
||||||
|
|
||||||
This base64 decodes the secret and writes it to a local file called `override.ini`. Make any necessary config changes to that file.
|
|
||||||
|
|
||||||
To apply the new config, first delete the existing copy of the secret:
|
|
||||||
|
|
||||||
```
|
|
||||||
kubectl -n atat delete secret atst-config-ini
|
|
||||||
```
|
|
||||||
|
|
||||||
Then create a new copy of the secret from your updated copy:
|
|
||||||
|
|
||||||
```
|
|
||||||
kubectl -n atat create secret generic atst-config-ini --from-file=./override.ini
|
|
||||||
```
|
|
||||||
|
|
||||||
Notes:
|
|
||||||
|
|
||||||
- Be careful not to check the override.ini file into source control.
|
|
||||||
- Be careful not to overwrite one CSP cluster's config with the other's. This will break everything.
|
|
||||||
|
|
||||||
### nginx-htpasswd
|
### nginx-htpasswd
|
||||||
|
|
||||||
If the site is running in dev mode, the `/login-dev` endpoint is available. This endpoint is protected by basic HTTP auth. To create a new password file, run:
|
If the site is running in dev mode, the `/login-dev` endpoint is available. This endpoint is protected by basic HTTP auth. To create a new password file, run:
|
||||||
@ -178,11 +149,32 @@ az keyvault secret set --vault-name <VAULT NAME> --name <NAME OF PARAM> --value
|
|||||||
```
|
```
|
||||||
---
|
---
|
||||||
|
|
||||||
|
# Secrets Management
|
||||||
|
|
||||||
|
Secrets, keys, and certificates are managed from Azure Key Vault. These items are mounted into the containers at runtime using the FlexVol implementation described below.
|
||||||
|
|
||||||
|
The following are mounted into the NGINX container in the atst pod:
|
||||||
|
|
||||||
|
- The TLS certs for the site
|
||||||
|
- The DH parameter for TLS connections
|
||||||
|
|
||||||
|
These are mounted into every instance of the Flask application container (the atst container, the celery worker, etc.):
|
||||||
|
|
||||||
|
- The Azure storage key used to access blob storage (AZURE_STORAGE_KEY)
|
||||||
|
- The password for the SMTP server used to send mail (MAIL_PASSWORD)
|
||||||
|
- The Postgres database user password (PGPASSWORD)
|
||||||
|
- The Redis user password (REDIS_PASSWORD)
|
||||||
|
- The Flask secret key used for session signing and generating CSRF tokens (SECRET_KEY)
|
||||||
|
|
||||||
|
Secrets should be added to Key Vault with the following naming pattern: [branch/environment]-[all-caps config setting name]. Note that Key Vault does not support underscores. Substitute hyphens. For example, the config setting for the SMTP server password is MAIL_SERVER. The corresponding secret name in Key Vault is "master-MAIL-SERVER" for the credential used in the primary environment.These secrets are mounted into the containers via FlexVol.
|
||||||
|
|
||||||
|
To add or manage secrets, keys, and certificates in Key Vault, see the [documentation](https://docs.microsoft.com/en-us/azure/key-vault/quick-create-cli).
|
||||||
|
|
||||||
# Setting Up FlexVol for Secrets
|
# Setting Up FlexVol for Secrets
|
||||||
|
|
||||||
## Preparing Azure Environment
|
## Preparing Azure Environment
|
||||||
|
|
||||||
A Key Vault will need to be created. Save it's full id (the full path) for use later.
|
A Key Vault will need to be created. Save its full id (the full path) for use later.
|
||||||
|
|
||||||
## Preparing Cluster
|
## Preparing Cluster
|
||||||
|
|
||||||
|
@ -6,15 +6,28 @@ metadata:
|
|||||||
namespace: atat
|
namespace: atat
|
||||||
data:
|
data:
|
||||||
ASSETS_URL: https://atat-cdn.azureedge.net/
|
ASSETS_URL: https://atat-cdn.azureedge.net/
|
||||||
|
AZURE_ACCOUNT_NAME: atat
|
||||||
|
AZURE_TO_BUCKET_NAME: task-order-pdfs
|
||||||
BLOB_STORAGE_URL: https://atat.blob.core.windows.net/
|
BLOB_STORAGE_URL: https://atat.blob.core.windows.net/
|
||||||
|
CAC_URL: https://auth-staging.atat.code.mil/login-redirect
|
||||||
CDN_ORIGIN: https://azure.atat.code.mil
|
CDN_ORIGIN: https://azure.atat.code.mil
|
||||||
CELERY_DEFAULT_QUEUE: celery-master
|
CELERY_DEFAULT_QUEUE: celery-master
|
||||||
CSP: azure
|
CSP: azure
|
||||||
|
DEBUG: 0
|
||||||
FLASK_ENV: master
|
FLASK_ENV: master
|
||||||
LOG_JSON: "true"
|
LOG_JSON: "true"
|
||||||
OVERRIDE_CONFIG_FULLPATH: /opt/atat/atst/atst-overrides.ini
|
MAIL_PORT: 587
|
||||||
|
MAIL_SENDER: postmaster@atat.code.mil
|
||||||
|
MAIL_SERVER: smtp.mailgun.org
|
||||||
|
MAIL_TLS: "true"
|
||||||
|
OVERRIDE_CONFIG_DIRECTORY: /config
|
||||||
|
PGAPPNAME: atst
|
||||||
|
PGDATABASE: staging
|
||||||
|
PGHOST: atat-db.postgres.database.azure.com
|
||||||
|
PGPORT: 5432
|
||||||
PGSSLMODE: verify-full
|
PGSSLMODE: verify-full
|
||||||
PGSSLROOTCERT: /opt/atat/atst/ssl/pgsslrootcert.crt
|
PGSSLROOTCERT: /opt/atat/atst/ssl/pgsslrootcert.crt
|
||||||
|
PGUSER: atat_master@atat-db
|
||||||
REDIS_HOST: atat.redis.cache.windows.net:6380
|
REDIS_HOST: atat.redis.cache.windows.net:6380
|
||||||
REDIS_TLS: "true"
|
REDIS_TLS: "true"
|
||||||
STATIC_URL: https://atat-cdn.azureedge.net/static/
|
STATIC_URL: https://atat-cdn.azureedge.net/static/
|
||||||
|
@ -5,9 +5,25 @@ metadata:
|
|||||||
name: atst-worker-envvars
|
name: atst-worker-envvars
|
||||||
namespace: atat
|
namespace: atat
|
||||||
data:
|
data:
|
||||||
|
AZURE_ACCOUNT_NAME: atat
|
||||||
|
AZURE_TO_BUCKET_NAME: task-order-pdfs
|
||||||
|
CAC_URL: https://auth-staging.atat.code.mil/login-redirect
|
||||||
CELERY_DEFAULT_QUEUE: celery-master
|
CELERY_DEFAULT_QUEUE: celery-master
|
||||||
DISABLE_CRL_CHECK: "True"
|
DEBUG: 0
|
||||||
|
DISABLE_CRL_CHECK: "true"
|
||||||
|
MAIL_PORT: 587
|
||||||
|
MAIL_SENDER: postmaster@atat.code.mil
|
||||||
|
MAIL_SERVER: smtp.mailgun.org
|
||||||
|
MAIL_TLS: "true"
|
||||||
|
OVERRIDE_CONFIG_DIRECTORY: /config
|
||||||
|
PGAPPNAME: atst
|
||||||
|
PGDATABASE: staging
|
||||||
|
PGHOST: atat-db.postgres.database.azure.com
|
||||||
|
PGPORT: 5432
|
||||||
PGSSLMODE: verify-full
|
PGSSLMODE: verify-full
|
||||||
PGSSLROOTCERT: /opt/atat/atst/ssl/pgsslrootcert.crt
|
PGSSLROOTCERT: /opt/atat/atst/ssl/pgsslrootcert.crt
|
||||||
|
PGUSER: atat_master@atat-db
|
||||||
|
REDIS_HOST: atat.redis.cache.windows.net:6380
|
||||||
|
REDIS_TLS: "true"
|
||||||
SERVER_NAME: azure.atat.code.mil
|
SERVER_NAME: azure.atat.code.mil
|
||||||
TZ: UTC
|
TZ: UTC
|
||||||
|
@ -34,9 +34,6 @@ spec:
|
|||||||
- configMapRef:
|
- configMapRef:
|
||||||
name: atst-envvars
|
name: atst-envvars
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- name: atst-config
|
|
||||||
mountPath: "/opt/atat/atst/atst-overrides.ini"
|
|
||||||
subPath: atst-overrides.ini
|
|
||||||
- name: nginx-client-ca-bundle
|
- name: nginx-client-ca-bundle
|
||||||
mountPath: "/opt/atat/atst/ssl/server-certs/ca-chain.pem"
|
mountPath: "/opt/atat/atst/ssl/server-certs/ca-chain.pem"
|
||||||
subPath: client-ca-bundle.pem
|
subPath: client-ca-bundle.pem
|
||||||
@ -50,6 +47,8 @@ spec:
|
|||||||
- name: uwsgi-config
|
- name: uwsgi-config
|
||||||
mountPath: "/opt/atat/atst/uwsgi.ini"
|
mountPath: "/opt/atat/atst/uwsgi.ini"
|
||||||
subPath: uwsgi.ini
|
subPath: uwsgi.ini
|
||||||
|
- name: flask-secret
|
||||||
|
mountPath: "/config"
|
||||||
- name: nginx
|
- name: nginx
|
||||||
image: nginx:alpine
|
image: nginx:alpine
|
||||||
ports:
|
ports:
|
||||||
@ -79,13 +78,6 @@ spec:
|
|||||||
- name: nginx-secret
|
- name: nginx-secret
|
||||||
mountPath: "/etc/ssl/"
|
mountPath: "/etc/ssl/"
|
||||||
volumes:
|
volumes:
|
||||||
- name: atst-config
|
|
||||||
secret:
|
|
||||||
secretName: atst-config-ini
|
|
||||||
items:
|
|
||||||
- key: override.ini
|
|
||||||
path: atst-overrides.ini
|
|
||||||
mode: 0644
|
|
||||||
- name: nginx-client-ca-bundle
|
- name: nginx-client-ca-bundle
|
||||||
configMap:
|
configMap:
|
||||||
name: nginx-client-ca-bundle
|
name: nginx-client-ca-bundle
|
||||||
@ -141,6 +133,16 @@ spec:
|
|||||||
keyvaultobjectaliases: "dhparam.pem;atat.key;atat.crt"
|
keyvaultobjectaliases: "dhparam.pem;atat.key;atat.crt"
|
||||||
keyvaultobjecttypes: "secret;secret;secret"
|
keyvaultobjecttypes: "secret;secret;secret"
|
||||||
tenantid: $TENANT_ID
|
tenantid: $TENANT_ID
|
||||||
|
- name: flask-secret
|
||||||
|
flexVolume:
|
||||||
|
driver: "azure/kv"
|
||||||
|
options:
|
||||||
|
usepodidentity: "true"
|
||||||
|
keyvaultname: "atat-vault-test"
|
||||||
|
keyvaultobjectnames: "master-AZURE-STORAGE-KEY;master-MAIL-PASSWORD;master-PGPASSWORD;master-REDIS-PASSWORD;master-SECRET-KEY"
|
||||||
|
keyvaultobjectaliases: "AZURE_STORAGE_KEY;MAIL_PASSWORD;PGPASSWORD;REDIS_PASSWORD;SECRET_KEY"
|
||||||
|
keyvaultobjecttypes: "secret;secret;secret;secret;key"
|
||||||
|
tenantid: $TENANT_ID
|
||||||
---
|
---
|
||||||
apiVersion: extensions/v1beta1
|
apiVersion: extensions/v1beta1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
@ -161,6 +163,7 @@ spec:
|
|||||||
labels:
|
labels:
|
||||||
app: atst
|
app: atst
|
||||||
role: worker
|
role: worker
|
||||||
|
aadpodidbinding: atat-kv-id-binding
|
||||||
spec:
|
spec:
|
||||||
securityContext:
|
securityContext:
|
||||||
fsGroup: 101
|
fsGroup: 101
|
||||||
@ -182,20 +185,12 @@ spec:
|
|||||||
- configMapRef:
|
- configMapRef:
|
||||||
name: atst-worker-envvars
|
name: atst-worker-envvars
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- name: atst-config
|
|
||||||
mountPath: "/opt/atat/atst/atst-overrides.ini"
|
|
||||||
subPath: atst-overrides.ini
|
|
||||||
- name: pgsslrootcert
|
- name: pgsslrootcert
|
||||||
mountPath: "/opt/atat/atst/ssl/pgsslrootcert.crt"
|
mountPath: "/opt/atat/atst/ssl/pgsslrootcert.crt"
|
||||||
subPath: pgsslrootcert.crt
|
subPath: pgsslrootcert.crt
|
||||||
|
- name: flask-secret
|
||||||
|
mountPath: "/config"
|
||||||
volumes:
|
volumes:
|
||||||
- name: atst-config
|
|
||||||
secret:
|
|
||||||
secretName: atst-config-ini
|
|
||||||
items:
|
|
||||||
- key: override.ini
|
|
||||||
path: atst-overrides.ini
|
|
||||||
mode: 0644
|
|
||||||
- name: pgsslrootcert
|
- name: pgsslrootcert
|
||||||
configMap:
|
configMap:
|
||||||
name: pgsslrootcert
|
name: pgsslrootcert
|
||||||
@ -203,6 +198,16 @@ spec:
|
|||||||
- key: cert
|
- key: cert
|
||||||
path: pgsslrootcert.crt
|
path: pgsslrootcert.crt
|
||||||
mode: 0666
|
mode: 0666
|
||||||
|
- name: flask-secret
|
||||||
|
flexVolume:
|
||||||
|
driver: "azure/kv"
|
||||||
|
options:
|
||||||
|
usepodidentity: "true"
|
||||||
|
keyvaultname: "atat-vault-test"
|
||||||
|
keyvaultobjectnames: "master-AZURE-STORAGE-KEY;master-MAIL-PASSWORD;master-PGPASSWORD;master-REDIS-PASSWORD;master-SECRET-KEY"
|
||||||
|
keyvaultobjectaliases: "AZURE_STORAGE_KEY;MAIL_PASSWORD;PGPASSWORD;REDIS_PASSWORD;SECRET_KEY"
|
||||||
|
keyvaultobjecttypes: "secret;secret;secret;secret;key"
|
||||||
|
tenantid: $TENANT_ID
|
||||||
---
|
---
|
||||||
apiVersion: extensions/v1beta1
|
apiVersion: extensions/v1beta1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
@ -223,6 +228,7 @@ spec:
|
|||||||
labels:
|
labels:
|
||||||
app: atst
|
app: atst
|
||||||
role: beat
|
role: beat
|
||||||
|
aadpodidbinding: atat-kv-id-binding
|
||||||
spec:
|
spec:
|
||||||
securityContext:
|
securityContext:
|
||||||
fsGroup: 101
|
fsGroup: 101
|
||||||
@ -244,20 +250,12 @@ spec:
|
|||||||
- configMapRef:
|
- configMapRef:
|
||||||
name: atst-worker-envvars
|
name: atst-worker-envvars
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- name: atst-config
|
|
||||||
mountPath: "/opt/atat/atst/atst-overrides.ini"
|
|
||||||
subPath: atst-overrides.ini
|
|
||||||
- name: pgsslrootcert
|
- name: pgsslrootcert
|
||||||
mountPath: "/opt/atat/atst/ssl/pgsslrootcert.crt"
|
mountPath: "/opt/atat/atst/ssl/pgsslrootcert.crt"
|
||||||
subPath: pgsslrootcert.crt
|
subPath: pgsslrootcert.crt
|
||||||
|
- name: flask-secret
|
||||||
|
mountPath: "/config"
|
||||||
volumes:
|
volumes:
|
||||||
- name: atst-config
|
|
||||||
secret:
|
|
||||||
secretName: atst-config-ini
|
|
||||||
items:
|
|
||||||
- key: override.ini
|
|
||||||
path: atst-overrides.ini
|
|
||||||
mode: 0644
|
|
||||||
- name: pgsslrootcert
|
- name: pgsslrootcert
|
||||||
configMap:
|
configMap:
|
||||||
name: pgsslrootcert
|
name: pgsslrootcert
|
||||||
@ -265,6 +263,16 @@ spec:
|
|||||||
- key: cert
|
- key: cert
|
||||||
path: pgsslrootcert.crt
|
path: pgsslrootcert.crt
|
||||||
mode: 0666
|
mode: 0666
|
||||||
|
- name: flask-secret
|
||||||
|
flexVolume:
|
||||||
|
driver: "azure/kv"
|
||||||
|
options:
|
||||||
|
usepodidentity: "true"
|
||||||
|
keyvaultname: "atat-vault-test"
|
||||||
|
keyvaultobjectnames: "master-AZURE-STORAGE-KEY;master-MAIL-PASSWORD;master-PGPASSWORD;master-REDIS-PASSWORD;master-SECRET-KEY"
|
||||||
|
keyvaultobjectaliases: "AZURE_STORAGE_KEY;MAIL_PASSWORD;PGPASSWORD;REDIS_PASSWORD;SECRET_KEY"
|
||||||
|
keyvaultobjecttypes: "secret;secret;secret;secret;key"
|
||||||
|
tenantid: $TENANT_ID
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Service
|
kind: Service
|
||||||
|
@ -10,6 +10,11 @@ spec:
|
|||||||
jobTemplate:
|
jobTemplate:
|
||||||
spec:
|
spec:
|
||||||
template:
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: atst
|
||||||
|
role: crl-sync
|
||||||
|
aadpodidbinding: atat-kv-id-binding
|
||||||
spec:
|
spec:
|
||||||
restartPolicy: OnFailure
|
restartPolicy: OnFailure
|
||||||
containers:
|
containers:
|
||||||
@ -27,19 +32,21 @@ spec:
|
|||||||
- configMapRef:
|
- configMapRef:
|
||||||
name: atst-worker-envvars
|
name: atst-worker-envvars
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- name: atst-config
|
|
||||||
mountPath: "/opt/atat/atst/atst-overrides.ini"
|
|
||||||
subPath: atst-overrides.ini
|
|
||||||
- name: crls-vol
|
- name: crls-vol
|
||||||
mountPath: "/opt/atat/atst/crls"
|
mountPath: "/opt/atat/atst/crls"
|
||||||
|
- name: flask-secret
|
||||||
|
mountPath: "/config"
|
||||||
volumes:
|
volumes:
|
||||||
- name: atst-config
|
|
||||||
secret:
|
|
||||||
secretName: atst-config-ini
|
|
||||||
items:
|
|
||||||
- key: override.ini
|
|
||||||
path: atst-overrides.ini
|
|
||||||
mode: 0644
|
|
||||||
- name: crls-vol
|
- name: crls-vol
|
||||||
persistentVolumeClaim:
|
persistentVolumeClaim:
|
||||||
claimName: crls-vol-claim
|
claimName: crls-vol-claim
|
||||||
|
- name: flask-secret
|
||||||
|
flexVolume:
|
||||||
|
driver: "azure/kv"
|
||||||
|
options:
|
||||||
|
usepodidentity: "true"
|
||||||
|
keyvaultname: "atat-vault-test"
|
||||||
|
keyvaultobjectnames: "master-AZURE-STORAGE-KEY;master-MAIL-PASSWORD;master-PGPASSWORD;master-REDIS-PASSWORD;master-SECRET-KEY"
|
||||||
|
keyvaultobjectaliases: "AZURE_STORAGE_KEY;MAIL_PASSWORD;PGPASSWORD;REDIS_PASSWORD;SECRET_KEY"
|
||||||
|
keyvaultobjecttypes: "secret;secret;secret;secret;key"
|
||||||
|
tenantid: $TENANT_ID
|
||||||
|
@ -11,3 +11,52 @@ spec:
|
|||||||
options:
|
options:
|
||||||
keyvaultname: "atat-vault-test"
|
keyvaultname: "atat-vault-test"
|
||||||
keyvaultobjectnames: "dhparam4096;staging-cert;staging-cert"
|
keyvaultobjectnames: "dhparam4096;staging-cert;staging-cert"
|
||||||
|
- name: flask-secret
|
||||||
|
flexVolume:
|
||||||
|
options:
|
||||||
|
keyvaultname: "atat-vault-test"
|
||||||
|
keyvaultobjectnames: "staging-AZURE-STORAGE-KEY;staging-MAIL-PASSWORD;staging-PGPASSWORD;staging-REDIS-PASSWORD;staging-SECRET-KEY"
|
||||||
|
---
|
||||||
|
apiVersion: extensions/v1beta1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: atst-worker
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
volumes:
|
||||||
|
- name: flask-secret
|
||||||
|
flexVolume:
|
||||||
|
options:
|
||||||
|
keyvaultname: "atat-vault-test"
|
||||||
|
keyvaultobjectnames: "staging-AZURE-STORAGE-KEY;staging-MAIL-PASSWORD;staging-PGPASSWORD;staging-REDIS-PASSWORD;staging-SECRET-KEY"
|
||||||
|
---
|
||||||
|
apiVersion: extensions/v1beta1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: atst-beat
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
volumes:
|
||||||
|
- name: flask-secret
|
||||||
|
flexVolume:
|
||||||
|
options:
|
||||||
|
keyvaultname: "atat-vault-test"
|
||||||
|
keyvaultobjectnames: "staging-AZURE-STORAGE-KEY;staging-MAIL-PASSWORD;staging-PGPASSWORD;staging-REDIS-PASSWORD;staging-SECRET-KEY"
|
||||||
|
---
|
||||||
|
apiVersion: batch/v1beta1
|
||||||
|
kind: CronJob
|
||||||
|
metadata:
|
||||||
|
name: crls
|
||||||
|
spec:
|
||||||
|
jobTemplate:
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
volumes:
|
||||||
|
- name: flask-secret
|
||||||
|
flexVolume:
|
||||||
|
options:
|
||||||
|
keyvaultname: "atat-vault-test"
|
||||||
|
keyvaultobjectnames: "staging-AZURE-STORAGE-KEY;staging-MAIL-PASSWORD;staging-PGPASSWORD;staging-REDIS-PASSWORD;staging-SECRET-KEY"
|
||||||
|
@ -7,6 +7,11 @@ spec:
|
|||||||
ttlSecondsAfterFinished: 100
|
ttlSecondsAfterFinished: 100
|
||||||
backoffLimit: 2
|
backoffLimit: 2
|
||||||
template:
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: atst
|
||||||
|
role: migration
|
||||||
|
aadpodidbinding: atat-kv-id-binding
|
||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- name: migration
|
- name: migration
|
||||||
@ -28,20 +33,12 @@ spec:
|
|||||||
- configMapRef:
|
- configMapRef:
|
||||||
name: atst-worker-envvars
|
name: atst-worker-envvars
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- name: atst-config
|
|
||||||
mountPath: "/opt/atat/atst/atst-overrides.ini"
|
|
||||||
subPath: atst-overrides.ini
|
|
||||||
- name: pgsslrootcert
|
- name: pgsslrootcert
|
||||||
mountPath: "/opt/atat/atst/ssl/pgsslrootcert.crt"
|
mountPath: "/opt/atat/atst/ssl/pgsslrootcert.crt"
|
||||||
subPath: pgsslrootcert.crt
|
subPath: pgsslrootcert.crt
|
||||||
|
- name: flask-secret
|
||||||
|
mountPath: "/config"
|
||||||
volumes:
|
volumes:
|
||||||
- name: atst-config
|
|
||||||
secret:
|
|
||||||
secretName: atst-config-ini
|
|
||||||
items:
|
|
||||||
- key: override.ini
|
|
||||||
path: atst-overrides.ini
|
|
||||||
mode: 0644
|
|
||||||
- name: pgsslrootcert
|
- name: pgsslrootcert
|
||||||
configMap:
|
configMap:
|
||||||
name: pgsslrootcert
|
name: pgsslrootcert
|
||||||
@ -49,4 +46,14 @@ spec:
|
|||||||
- key: cert
|
- key: cert
|
||||||
path: pgsslrootcert.crt
|
path: pgsslrootcert.crt
|
||||||
mode: 0666
|
mode: 0666
|
||||||
|
- name: flask-secret
|
||||||
|
flexVolume:
|
||||||
|
driver: "azure/kv"
|
||||||
|
options:
|
||||||
|
usepodidentity: "true"
|
||||||
|
keyvaultname: "atat-vault-test"
|
||||||
|
keyvaultobjectnames: "master-AZURE-STORAGE-KEY;master-MAIL-PASSWORD;master-PGPASSWORD;master-REDIS-PASSWORD;master-SECRET-KEY"
|
||||||
|
keyvaultobjectaliases: "AZURE_STORAGE_KEY;MAIL_PASSWORD;PGPASSWORD;REDIS_PASSWORD;SECRET_KEY"
|
||||||
|
keyvaultobjecttypes: "secret;secret;secret;secret;key"
|
||||||
|
tenantid: $TENANT_ID
|
||||||
restartPolicy: Never
|
restartPolicy: Never
|
||||||
|
@ -1,8 +1,13 @@
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
|
from configparser import ConfigParser
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from atst.app import make_crl_validator
|
from atst.app import (
|
||||||
|
make_crl_validator,
|
||||||
|
apply_config_from_directory,
|
||||||
|
apply_config_from_environment,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
@ -22,3 +27,43 @@ def test_make_crl_validator_creates_crl_dir(app, tmpdir, replace_crl_dir_config)
|
|||||||
replace_crl_dir_config(crl_dir)
|
replace_crl_dir_config(crl_dir)
|
||||||
make_crl_validator(app)
|
make_crl_validator(app)
|
||||||
assert os.path.isdir(crl_dir)
|
assert os.path.isdir(crl_dir)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def config_object():
|
||||||
|
config = ConfigParser()
|
||||||
|
config.optionxform = str
|
||||||
|
config.read_string("[default]\nFOO=BALONEY")
|
||||||
|
return config
|
||||||
|
|
||||||
|
|
||||||
|
def test_apply_config_from_directory(tmpdir, config_object):
|
||||||
|
config_setting = tmpdir.join("FOO")
|
||||||
|
with open(config_setting, "w") as conf_file:
|
||||||
|
conf_file.write("MAYO")
|
||||||
|
|
||||||
|
apply_config_from_directory(tmpdir, config_object)
|
||||||
|
assert config_object.get("default", "FOO") == "MAYO"
|
||||||
|
|
||||||
|
|
||||||
|
def test_apply_config_from_directory_skips_unknown_settings(tmpdir, config_object):
|
||||||
|
config_setting = tmpdir.join("FLARF")
|
||||||
|
with open(config_setting, "w") as conf_file:
|
||||||
|
conf_file.write("MAYO")
|
||||||
|
|
||||||
|
apply_config_from_directory(tmpdir, config_object)
|
||||||
|
assert "FLARF" not in config_object.options("default")
|
||||||
|
|
||||||
|
|
||||||
|
def test_apply_config_from_environment(monkeypatch, config_object):
|
||||||
|
monkeypatch.setenv("FOO", "MAYO")
|
||||||
|
apply_config_from_environment(config_object)
|
||||||
|
assert config_object.get("default", "FOO") == "MAYO"
|
||||||
|
|
||||||
|
|
||||||
|
def test_apply_config_from_environment_skips_unknown_settings(
|
||||||
|
monkeypatch, config_object
|
||||||
|
):
|
||||||
|
monkeypatch.setenv("FLARF", "MAYO")
|
||||||
|
apply_config_from_environment(config_object)
|
||||||
|
assert "FLARF" not in config_object.options("default")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user