Skip to content

Commit f828dac

Browse files
committed
Add ability to source inital user configuration from AWS SM
1 parent 141a807 commit f828dac

4 files changed

Lines changed: 120 additions & 26 deletions

File tree

README.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,44 @@ updateTektonDefinitions(pipelinesNamespace, "/mascli/templates/ibm-mas-tekton.ya
3737
pipelineURL = launchUpgradePipeline(self.dynamicClient, instanceId)
3838
print(pipelineURL)
3939
```
40+
41+
42+
mas-devops-create-initial-users
43+
---------------------------------------------
44+
45+
46+
```bash
47+
SM_AWS_REGION=""
48+
SM_AWS_ACCESS_KEY_ID=""
49+
SM_AWS_SECRET_ACCESS_KEY=""
50+
51+
aws configure set default.region ${SM_AWS_REGION}
52+
aws configure set aws_access_key_id ${SM_AWS_ACCESS_KEY_ID}
53+
aws configure set aws_secret_access_key ${SM_AWS_SECRET_ACCESS_KEY}
54+
55+
56+
oc login --token=sha256~xxx --server=https://xxx:6443
57+
58+
oc port-forward service/admin-dashboard 8445:443 -n mas-tgk01-core
59+
oc port-forward service/coreapi 8444:443 -n mas-tgk01-core
60+
oc port-forward service/tgk01-masdev 8443:443 -n mas-tgk01-manage
61+
62+
mas-devops-create-initial-users-for-saas \
63+
--mas-instance-id tgk01 \
64+
--mas-workspace-id masdev \
65+
--log-level INFO \
66+
--initial-users-secret-name "aws-dev/noble4/tgk01/initial_users" \
67+
--manage-api-port 8443 \
68+
--coreapi-port 8444 \
69+
--admin-dashboard-port 8445
70+
71+
72+
mas-devops-create-initial-users-for-saas \
73+
--mas-instance-id tgk01 \
74+
--mas-workspace-id masdev \
75+
--log-level INFO \
76+
--initial-users-yaml-file /home/tom/workspaces/notes/mascore3423/example-users-single.yaml \
77+
--manage-api-port 8443 \
78+
--coreapi-port 8444 \
79+
--admin-dashboard-port 8445
80+
```

bin/mas-devops-create-initial-users-for-saas

Lines changed: 48 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,12 @@ import argparse
1616
import logging
1717
import urllib3
1818
urllib3.disable_warnings()
19-
import os
20-
import sys
21-
import json
22-
import re
2319
import yaml
20+
import json
21+
import sys
22+
23+
import boto3
24+
from botocore.exceptions import ClientError
2425

2526
from mas.devops.users import MASUserUtils
2627

@@ -30,18 +31,20 @@ if __name__ == "__main__":
3031
parser = argparse.ArgumentParser()
3132

3233
# Primary Options
34+
parser.add_argument("--mas-account-id", required=False) # TODO: remove if unused
35+
parser.add_argument("--mas-cluster-id", required=False) # TODO: remove if unused
3336
parser.add_argument("--mas-instance-id", required=True)
3437
parser.add_argument("--mas-workspace-id", required=True)
35-
parser.add_argument("--initial-users-yaml-file", required=True)
3638
parser.add_argument("--log-level", required=False, choices=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"], default="WARNING")
37-
parser.add_argument("--dry-run", required=False, help="When specified, nothing will actually be deleted from the cluster", action="store_true")
38-
39-
4039
parser.add_argument("--coreapi-port", required=False, default=443)
4140
parser.add_argument("--admin-dashboard-port", required=False, default=443)
4241
parser.add_argument("--manage-api-port", required=False, default=443)
4342

4443

44+
group = parser.add_mutually_exclusive_group(required=True)
45+
group.add_argument("--initial-users-yaml-file")
46+
group.add_argument("--initial-users-secret-name")
47+
4548
args, unknown = parser.parse_known_args()
4649

4750
log_level = getattr(logging, args.log_level)
@@ -57,26 +60,29 @@ if __name__ == "__main__":
5760
ch.setFormatter(chFormatter)
5861
logger.addHandler(ch)
5962

60-
63+
mas_account_id = args.mas_account_id
64+
mas_cluster_id = args.mas_cluster_id
6165
mas_instance_id = args.mas_instance_id
6266
mas_workspace_id = args.mas_workspace_id
6367
initial_users_yaml_file = args.initial_users_yaml_file
64-
dry_run = args.dry_run
68+
initial_users_secret_name = args.initial_users_secret_name
6569
coreapi_port = args.coreapi_port
6670
admin_dashboard_port = args.admin_dashboard_port
6771
manage_api_port = args.manage_api_port
6872

6973

7074
logger.info("Configuration:")
7175
logger.info("--------------")
72-
logger.info(f"mas_instance_id: {mas_instance_id}")
73-
logger.info(f"mas_workspace_id: {mas_workspace_id}")
74-
logger.info(f"initial_users_yaml_file: {initial_users_yaml_file}")
75-
logger.info(f"log_level: {log_level}")
76-
logger.info(f"dry_run: {dry_run}")
77-
logger.info(f"coreapi_port: {coreapi_port}")
78-
logger.info(f"admin_dashboard_port: {admin_dashboard_port}")
79-
logger.info(f"manage_api_port: {manage_api_port}")
76+
logger.info(f"mas_account_id: {mas_account_id}")
77+
logger.info(f"mas_cluster_id: {mas_cluster_id}")
78+
logger.info(f"mas_instance_id: {mas_instance_id}")
79+
logger.info(f"mas_workspace_id: {mas_workspace_id}")
80+
logger.info(f"initial_users_yaml_file: {initial_users_yaml_file}")
81+
logger.info(f"initial_users_secret_name: {initial_users_secret_name}")
82+
logger.info(f"log_level: {log_level}")
83+
logger.info(f"coreapi_port: {coreapi_port}")
84+
logger.info(f"admin_dashboard_port: {admin_dashboard_port}")
85+
logger.info(f"manage_api_port: {manage_api_port}")
8086
logger.info("")
8187

8288
try:
@@ -88,11 +94,30 @@ if __name__ == "__main__":
8894
config.load_kube_config()
8995
logger.debug("Loaded kubeconfig file")
9096

91-
user_utils = MASUserUtils(mas_instance_id, mas_workspace_id, client.api_client.ApiClient(), coreapi_port=coreapi_port, admin_dashboard_port=admin_dashboard_port, manage_api_port=manage_api_port)
92-
93-
with open(initial_users_yaml_file, 'r') as file:
94-
initial_users_yaml = yaml.safe_load(file)
9597

98+
user_utils = MASUserUtils(mas_instance_id, mas_workspace_id, client.api_client.ApiClient(), coreapi_port=coreapi_port, admin_dashboard_port=admin_dashboard_port, manage_api_port=manage_api_port)
9699

97-
user_utils.create_initial_users_for_saas(initial_users_yaml)
100+
if initial_users_secret_name is not None:
101+
102+
session = boto3.session.Session()
103+
aws_sm_client = session.client(
104+
service_name='secretsmanager',
105+
)
106+
try:
107+
initial_users_secret = aws_sm_client.get_secret_value( # pragma: allowlist secret
108+
SecretId=initial_users_secret_name
109+
)
110+
except ClientError as e:
111+
raise Exception(f"Failed to fetch secret {initial_users_secret_name}: {str(e)}")
112+
113+
secret_json = json.loads(initial_users_secret['SecretString'])
114+
initial_users = user_utils.parse_initial_users_from_aws_secret_json(secret_json)
115+
elif initial_users_yaml_file is not None:
116+
with open(initial_users_yaml_file, 'r') as file:
117+
initial_users = yaml.safe_load(file)
118+
else:
119+
raise Exception("Something unexpected happened")
120+
121+
user_utils.create_initial_users_for_saas(initial_users)
122+
98123

setup.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ def get_version(rel_path):
6060
'kubernetes', # Apache Software License
6161
'kubeconfig', # BSD License
6262
'jinja2', # BSD License
63-
'jinja2-base64-filters' # MIT License
63+
'jinja2-base64-filters', # MIT License
64+
'boto3'
6465
],
6566
extras_require={
6667
'dev': [

src/mas/devops/users.py

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@
2727
MVI / other apps?
2828
unit tests
2929
30-
dry-run support
31-
3230
where are we going to run this from? Needs to run in cluster, so a Job in an app
3331
which app though? Manage?
3432
Perhaps we do the core bits in a core app (suite workspace?)
@@ -830,6 +828,35 @@ def await_mas_application_availability(self, mas_application_id, timeout_secs=60
830828
time.sleep(5)
831829
raise Exception(f"{mas_application_id} did not become ready and available in time, aborting")
832830

831+
def parse_initial_users_from_aws_secret_json(self, secret_json):
832+
primary = []
833+
secondary = []
834+
for (email, csv) in secret_json.items():
835+
values = csv.split(",")
836+
user_type = values[0].strip()
837+
given_name = values[1].strip()
838+
family_name = values[2].strip()
839+
840+
user = {
841+
"email": email,
842+
"given_name": given_name,
843+
"family_name": family_name
844+
}
845+
if user_type == "primary":
846+
primary.append(user)
847+
elif user_type == "secondary":
848+
secondary.append(user)
849+
else:
850+
raise Exception(f"Unknown user type for {email}: {user_type}")
851+
852+
initial_users = {
853+
"users": {
854+
"primary": primary,
855+
"secondary": secondary
856+
}
857+
}
858+
return initial_users
859+
833860
def create_initial_users_for_saas(self, initial_users):
834861

835862
# Validate input

0 commit comments

Comments
 (0)