-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Feature batch-create, multi-hosts (#27)
#### FEATURES/ENHANCEMENTS: - Support multi-hosts command to add multiple hostnames and respective origins to a single delivery/property configuration and include all of those hostnames into the new security configuration - The command requires a new input file in a CSV format - Support three standard akamai product: prd_SPM, prd_Fresca, prd_API_Accel - Support batch-create command to add multiple hostnames and respective origins to one or more delivery/property configurations and optionally add all of those hostnames to an existing security configuration and policy match target - The command requires a new input file in a CSV format - Support three standard akamai product: prd_SPM, prd_Fresca, prd_API_Accel #### MISC: - Allow short arguments i.e. both --file and -f will work - Rename sample setup files that are easier to identify for each command - Display proper version for --version and -h command - Provide sample setup files via new command fetch-sample-templates --------- Co-authored-by: Peak Wongcharoen <pwongcha@akamai.com>, Julie Sulkin <jsulkin@akamai.com>
- Loading branch information
1 parent
157d464
commit c738ffd
Showing
31 changed files
with
4,420 additions
and
484 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,5 +3,7 @@ | |
*logs* | ||
.DS_Store | ||
.venv | ||
.DS_Store | ||
.vscode | ||
.scripts | ||
.templates | ||
sample_templates |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,18 @@ | ||
# RELEASE NOTES | ||
|
||
## 2.1.0 (February 28, 2023) | ||
## 2.2.0 | ||
|
||
#### FEATURES/ENHANCEMENTS: | ||
|
||
* Support for secure by default certificates on both single-host and create setup types | ||
* Updated setup.json and setup_single_host.json templates to include secure_by_default option | ||
|
||
- Support multi-hosts command to add multiple hostnames and respective origins to a single delivery/property configuration and include all of those hostnames into the new security configuration | ||
- The command requires a new input file in a CSV format | ||
- Support three standard akamai product: prd_SPM, prd_Fresca, prd_API_Accel | ||
- Support batch-create command to add multiple hostnames and respective origins to one or more delivery/property configurations and optionally add all of those hostnames to an existing security configuration and policy match target | ||
- The command requires a new input file in a CSV format | ||
- Support three standard akamai product: prd_SPM, prd_Fresca, prd_API_Accel | ||
|
||
#### MISC: | ||
|
||
* Added validation check to hostnames | ||
- Allow short arguments i.e. both --file and -f will work | ||
- Rename sample setup files that are easier to identify for each command | ||
- Display proper version for --version and -h command |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
""" | ||
Copyright 2022 Akamai Technologies, Inc. All Rights Reserved. | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
""" | ||
from __future__ import annotations | ||
|
||
from dataclasses import dataclass | ||
from dataclasses import field | ||
|
||
from exceptions import setup_logger | ||
|
||
|
||
logger = setup_logger() | ||
|
||
|
||
@dataclass | ||
class MultiHosts: | ||
property_name: str | ||
contract_id: str | ||
product_id: str | ||
public_hostnames: list | ||
secure_by_default: bool | ||
edge_hostname: str | ||
notification_emails: list | ||
individual_cpcode: bool | ||
|
||
origin_default: str = '' | ||
group_id: str = '' | ||
edge_hostname_mode: str = 'use_existing_edgehostname' | ||
edge_hostname_id: int = 0 | ||
|
||
# general | ||
secure_network: str = 'ENHANCED_TLS' | ||
rule_format: str = 'latest' | ||
create_new_cpcode: bool = True | ||
individual_cpcode: bool = False | ||
new_cpcode_name: list[int] = field(default_factory=list) | ||
version_notes: str = 'Initial Version' | ||
|
||
onboard_default_cpcode: int = 0 | ||
onboard_property_id: str = '' | ||
|
||
# setup input files | ||
use_file: bool = True | ||
source_template_file: str = '' | ||
source_values_file: str = '' | ||
|
||
# pipeline | ||
use_folder: bool = False | ||
folder_path: str = '' | ||
env_name: str = '' | ||
|
||
# cert | ||
secure_by_default_new_ehn: bool = True | ||
secure_by_default_use_existing_ehn: str = '' | ||
use_existing_enrollment_id: bool = False | ||
existing_enrollment_id: int = 0 | ||
create_new_ssl_cert: bool = False | ||
ssl_cert_template_file: str = '' | ||
ssl_cert_template_values: str = '' | ||
temp_existing_edge_hostname: str = 'xxx' | ||
|
||
# waf info | ||
waf_config_name: str = 'WAF Security File' | ||
create_new_security_config: bool = True | ||
add_selected_host: bool = True | ||
update_match_target: bool = True | ||
waf_match_target_id: str = '' | ||
onboard_waf_config_id: int = 0 | ||
onboard_waf_prev_version: int = 0 | ||
onboard_waf_config_version: int = 0 | ||
policy_id: str = '' | ||
policy_name: str = 'Default' | ||
target_seq: int = 0 | ||
target_id: int = 0 | ||
|
||
# Staging activation | ||
activate_property_staging: bool = True | ||
activate_waf_policy_staging: bool = True | ||
|
||
# Production activation | ||
activate_property_production: bool = True | ||
activate_waf_policy_production: bool = True | ||
|
||
def add(self, name: str): | ||
self.new_cpcode_name.append(name) | ||
logger.debug(f'{self.new_cpcode_name=}') | ||
|
||
def update_origin_default(self, origin_hostname: str): | ||
self.origin_default = origin_hostname |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
""" | ||
Copyright 2019 Akamai Technologies, Inc. All Rights Reserved. | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
""" | ||
from __future__ import annotations | ||
|
||
import os | ||
from pathlib import Path | ||
|
||
from exceptions import setup_logger | ||
logger = setup_logger() | ||
|
||
|
||
class onboard: | ||
# Initialize the object | ||
def __init__(self, config, click_args): | ||
# Read values from setup.json or --file | ||
# Certain values (onboard_) are updated in main processing later | ||
try: | ||
self.property_name = [] | ||
self.csv_loc = click_args['csv'] | ||
self.property_list = [] | ||
self.valid_csv = True | ||
self.csv_dict = [] | ||
self.secure_network = click_args['network'] | ||
self.ehn_suffix = '.edgekey.net' | ||
if self.secure_network == 'STANDARD_TLS': | ||
self.ehn_suffix = 'edgesuite.net' | ||
self.contract_id = click_args['contract'] | ||
self.group_id = click_args['group'] | ||
self.product_id = click_args['product'] | ||
self.rule_format = click_args['rule_format'] | ||
self.create_new_cpcode = True | ||
self.source_template_file = click_args['template'] | ||
self.source_template_file = self.get_actual_location(self.source_template_file) | ||
self.level_0_rules = [] | ||
|
||
self.public_hostnames = [] | ||
|
||
self.onboard_property_id = None | ||
self.onboard_default_cpcode = 0 | ||
self.edge_hostname_id = 0 | ||
self.edge_hostname_list = [] | ||
# Edge hostname values | ||
if click_args['secure_by_default']: | ||
self.edge_hostname_mode = 'secure_by_default' | ||
else: | ||
self.edge_hostname_mode = 'use_existing_edgehostname' | ||
|
||
# WAF values | ||
if click_args['waf_config']: | ||
self.add_selected_host = True | ||
else: | ||
self.add_selected_host = False | ||
|
||
self.waf_config_name = click_args['waf_config'] | ||
|
||
if click_args['waf_match_target']: | ||
self.update_match_target = True | ||
else: | ||
self.update_match_target = False | ||
self.waf_match_target_id = click_args['waf_match_target'] | ||
if isinstance(self.waf_match_target_id, str): | ||
if self.waf_match_target_id == '': | ||
self.waf_match_target_id = 0 | ||
else: | ||
self.waf_match_target_id = int(self.waf_match_target_id) | ||
|
||
self.onboard_waf_config_id = None | ||
self.onboard_waf_config_version = None | ||
self.onboard_waf_prev_version = None | ||
|
||
self.activate_property_staging = False | ||
self.activate_waf_policy_staging = False | ||
self.activate_property_production = False | ||
self.activate_waf_policy_production = False | ||
|
||
# Activation values | ||
if 'delivery-staging' in click_args['activate']: | ||
self.activate_property_staging = True | ||
if 'waf-staging' in click_args['activate']: | ||
self.activate_waf_policy_staging = True | ||
if 'delivery-production' in click_args['activate']: | ||
self.activate_property_production = True | ||
if 'waf-production' in click_args['activate']: | ||
self.activate_waf_policy_production = True | ||
|
||
if click_args['email']: | ||
self.notification_emails = click_args['email'] | ||
else: | ||
self.notification_emails = ['noreply@akamai.com'] | ||
self.version_notes = 'Created using Onboard CLI' | ||
|
||
# Read config object that contains the command line parameters | ||
if not config.edgerc: | ||
if not os.getenv('AKAMAI_EDGERC'): | ||
self.edgerc = os.path.join(os.path.expanduser('~'), '.edgerc') | ||
else: | ||
self.edgerc = os.getenv('AKAMAI_EDGERC') | ||
else: | ||
self.edgerc = config.edgerc | ||
|
||
if not config.section: | ||
if not os.getenv('AKAMAI_EDGERC_SECTION'): | ||
self.section = 'onboard' | ||
else: | ||
self.section = os.getenv('AKAMAI_EDGERC_SECTION') | ||
else: | ||
self.section = config.section | ||
|
||
except KeyError as k: | ||
print('\nInput file is missing ' + str(k)) | ||
exit(-1) | ||
|
||
def get_actual_location(self, file_location: str) -> str: | ||
abs_file_location = file_location | ||
home = str(Path.home()) | ||
if '~' in file_location: | ||
file_location = file_location.replace('~', '') | ||
abs_file_location = f'{home}/{file_location}' | ||
|
||
return abs_file_location |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
""" | ||
Copyright 2023 Akamai Technologies, Inc. All Rights Reserved. | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
""" | ||
from __future__ import annotations | ||
|
||
import json | ||
import sys | ||
from pathlib import Path | ||
|
||
from exceptions import get_cli_root_directory | ||
from exceptions import setup_logger | ||
|
||
logger = setup_logger() | ||
root = get_cli_root_directory() | ||
|
||
|
||
class onboard: | ||
def __init__(self, json_input: dict): | ||
try: | ||
self.contract_id = json_input['property_info']['contract_id'] | ||
self.product_id = json_input['property_info']['product_id'] | ||
self.property_name = json_input['property_info']['property_name'] | ||
self.individual_cpcode = json_input['property_info']['individual_cpcode'] | ||
|
||
self.edge_hostname = json_input['edge_hostname']['use_existing_edge_hostname'] | ||
self.existing_enrollment_id = json_input['edge_hostname']['create_from_existing_enrollment_id'] | ||
|
||
try: | ||
self.secure_by_default = json_input['edge_hostname']['secure_by_default'] | ||
except KeyError as k: | ||
logger.warning('You are not using the latest template. Please use new setup.json template if you want to use secure by default') | ||
self.secure_by_default = False | ||
|
||
# The cpcode name contains one or more of these special characters ^ _ , # % ' \" ", | ||
self.new_cpcode_name = self.property_name.replace('_', ' ') | ||
|
||
# Security | ||
self.create_new_security_config = json_input['update_waf_info']['create_new_security_config'] | ||
self.waf_config_name = '' | ||
if len(json_input['update_waf_info']['waf_config_name']) > 0: | ||
self.waf_config_name = json_input['update_waf_info']['waf_config_name'] | ||
self.activate_production = json_input['activate_production'] | ||
self.notification_emails = json_input['notification_emails'] | ||
except KeyError as k: | ||
sys.exit(logger.error(f'Input file is missing {k}')) | ||
|
||
if isinstance(self.existing_enrollment_id, str): | ||
if self.existing_enrollment_id == '': | ||
self.existing_enrollment_id = 0 | ||
else: | ||
self.existing_enrollment_id = int(self.existing_enrollment_id) | ||
|
||
try: | ||
self.version_notes = json_input['property_info']['version_notes'] | ||
except: | ||
self.version_notes = '' | ||
|
||
def write_variable_json(self, default_origin: str, cp_code: int) -> None: | ||
""" | ||
Override origin server inside templates/variables.json which is hidden from user | ||
""" | ||
var = {} | ||
var['origin_default'] = default_origin | ||
var['cp_code'] = cp_code | ||
|
||
# override when run via CLI | ||
variable_file = Path(root, 'templates/akamai_product_templates/multi-hosts/variables.json') | ||
with variable_file.open('w') as file: | ||
json.dump(var, file, indent=4) | ||
|
||
# override when run via python script | ||
with Path('logs/variables.json').absolute().open('w') as file: | ||
json.dump(var, file, indent=4) | ||
|
||
def get_product_template(self, src_file: str) -> dict: | ||
with open(src_file) as f: | ||
rules = json.load(f) | ||
logger.debug(json.dumps(rules, indent=4)) | ||
return rules | ||
|
||
def override_product_template(self, onboard, rules: dict) -> None: | ||
# override when run via CLI | ||
template_file = Path(root, 'templates/akamai_product_templates/multi-hosts/multiple_hosts.json') | ||
with template_file.open('w') as file: | ||
json.dump(rules, file, indent=4) | ||
onboard.source_template_file = f'{template_file}' | ||
|
||
# override when run via python script | ||
with Path('logs/multiple_hosts.json').absolute().open('w') as file: | ||
json.dump(rules, file, indent=2) | ||
return None |
Oops, something went wrong.