netosecret.py - Python class and CLI
Python containing the NetoSecret class to encode and decode a netosecret string and a CLI to interact with the secret on command line.
CLI usage: python netosecret.py --help
You can run this as a standalone CLI for encoding and decoding netosecret values, or use the NetoSecret class in your Python.
"""Encode/Decode netosecret format for Netography API.
usage: netosecret.py [-h] [--url URL] [--appkey APPKEY] [--sharedsecret SHAREDSECRET] [--save SAVE] [--envname ENVNAME] [--print] [--decode] [--env] [--envfile ENVFILE] [shortname] [appname]
Encode/Decode netosecret format for Netography API.
positional arguments:
shortname Set the shortname
appname Set the appname
options:
-h, --help show this help message and exit
--url URL Set a custom API URL
--appkey APPKEY Set the appkey (prompt if not provided)
--sharedsecret SHAREDSECRET
Set the sharedsecret (prompt if not provided)
--save SAVE Save to env file
--envname ENVNAME Variable name to write to in envfile
--print Print the encoded netosecret
--decode Decode NETOSECRET and print the JSON (contains secrets)
--env Read all variables from environment
--envfile ENVFILE Read environment variables from the file
Example:
% python netosecret.py --appkey myappkey --sharedsecret mysharedsecret myshortname myappname
netosecret saved to netosecret.env
% python netosecret.py --decode --envfile netosecret.env
{
"url": "https://api.netography.com/api/v1",
"shortname": "myshortname",
"appname": "myappname",
"sharedsecret": "mysharedsecret",
"appkey": "myappkey"
}
% python netosecret.py --help
"""class NetoSecret definition
These 11 lines are all you need to replace setting the 5 individual authentication fields used by the Fusion APi with the netosecret.
NetoSecret.encode()
import argparse
import base64
import json
import os
from getpass import getpass
from typing import Dict
class NetoSecret:
@staticmethod
def encode(api_key: Dict[str, str]) -> str:
api_key_json = json.dumps(api_key)
api_key_base64 = base64.b64encode(api_key_json.encode()).decode()
return api_key_base64
@staticmethod
def decode(api_key_base64: str) -> Dict[str, str]:
api_key_json = base64.b64decode(api_key_base64).decode()
api_key = json.loads(api_key_json)
return api_keyNetoSecret.encode() takes Python Dict in this format and returns netosecret string.
{ "url":"", "shortname":"", "appname":"", "sharedsecret":"", "appkey":"" }
@staticmethod
def encode(api_key: Dict[str, str]) -> str:
api_key_json = json.dumps(api_key)
api_key_base64 = base64.b64encode(api_key_json.encode()).decode()
return api_key_base64NetoSecret.decode()
NetoSecret.decode() takes a netosecret string as argument and returns a Python Dict in format below:
{ "url":"", "shortname":"", "appname":"", "sharedsecret":"", "appkey":"" }
@staticmethod
def decode(api_key_base64: str) -> Dict[str, str]:
api_key_json = base64.b64decode(api_key_base64).decode()
api_key = json.loads(api_key_json)
return api_key
CLI argument parsing
Parses command line arguments when running this file
def get_env_value(is_secret: bool, *keys: str) -> str:
for key in keys:
value = os.getenv(key)
if value:
if is_secret:
print(f"Read from env {key}=******", file=os.stderr)
else:
print(f"Read from env {key}={value}", file=os.stderr)
return value
return ""
def main():
parser = argparse.ArgumentParser(
description="Encode/Decode netosecret format for Netography API."
)
parser.add_argument("shortname", nargs="?", help="Set the shortname")
parser.add_argument("appname", nargs="?", help="Set the appname")
parser.add_argument(
"--url",
help="Set a custom API URL",
default="https://api.netography.com/api/v1",
)
parser.add_argument("--appkey", help="Set the appkey (prompt if not provided)")
parser.add_argument(
"--sharedsecret", help="Set the sharedsecret (prompt if not provided)"
)
parser.add_argument("--save", help="Save to env file", default="netosecret.env")
parser.add_argument(
"--envname", help="Variable name to write to in envfile", default="NETOSECRET"
)
parser.add_argument(
"--print", action="store_true", help="Print the encoded netosecret"
)
parser.add_argument(
"--decode",
action="store_true",
help="Decode NETOSECRET and print the JSON (contains secrets)",
)
parser.add_argument(
"--env", action="store_true", help="Read all variables from environment"
)
parser.add_argument("--envfile", help="Read environment variables from the file")
args = parser.parse_args()
if args.envfile:
with open(args.envfile) as f:
for line in f:
if not line.startswith("#") and "=" in line:
key, value = line.strip().split("=", 1)
os.environ[key] = valueCLI: encode
Encodes individual authentication fields to netosecret string
if args.env or args.envfile:
args.url = (
get_env_value(False, "NETO__API__URL", "NETO_URL", "NETO__URL") or args.url
)
args.appname = (
get_env_value(False, "NETO__API__APP_NAME", "NETO_APP_NAME", "NETO_APPNAME")
or args.appname
)
args.shortname = (
get_env_value(
False, "NETO__API__SHORTNAME", "NETO_SHORTNAME", "NETO__SHORTNAME"
)
or args.shortname
)
args.sharedsecret = (
get_env_value(
True,
"NETO__API__CREDENTIALS__SHARED_SECRET",
"NETO_SHAREDSECRET",
"NETO__SHAREDSECRET",
"NETO_SHARED_SECRET",
)
or args.sharedsecret
)
args.appkey = (
get_env_value(
True,
"NETO__API__CREDENTIALS__APP_KEY",
"NETO__APPKEY",
"NETO__APP_KEY",
"NETO_APPKEY",
)
or args.appkey
)
if not args.shortname:
args.shortname = input("Enter shortname: ")
if not args.appname:
args.appname = input("Enter appname: ")
if not args.appkey:
args.appkey = getpass("Enter appkey: ")
if not args.sharedsecret:
args.sharedsecret = getpass("Enter sharedsecret: ")
if not all([args.shortname, args.appname, args.appkey, args.sharedsecret]):
parser.error(
"All fields (shortname, appname, appkey, sharedsecret) must be provided."
)
api_key = {
"url": args.url,
"shortname": args.shortname,
"appname": args.appname,
"sharedsecret": args.sharedsecret,
"appkey": args.appkey,
}
encoded = NetoSecret.encode(api_key)
if args.print:
print(encoded)
else:
with open(args.save, "w") as f:
f.write(f"{args.envname}={encoded}\n")
print(f"netosecret saved to {args.save}")
if __name__ == "__main__":
main()Last updated