Files
playground/legacy/aws_codecommit.py
T
2024-12-24 20:49:41 +03:00

337 lines
11 KiB
Python

import itertools
import json
import logging
import pprint
import re
from collections import defaultdict
from concurrent.futures import ThreadPoolExecutor
from urllib.parse import quote_plus
import boto3
import httpx
import urllib.parse
import subprocess
import typing
def list_repo_tags(*, repository_name: str, region: str, username: str, password: str) -> typing.List[dict]:
"""
Fetches the list of tags in a Codecommit repo using git ls-remote command
:returns: List of {tag, commit} items
"""
url = "https://{username}:{password}@git-codecommit.{region}.amazonaws.com/v1/repos/{repository_name}".format(
username=quote_plus(username),
password=quote_plus(password), # passwords are base64-encoded and might contain "/"
region=region,
repository_name=repository_name,
)
result = subprocess.run(["git", "ls-remote", "--refs", "--tags", url], text=True, stdout=subprocess.PIPE)
tags = []
for line in result.stdout.splitlines(keepends=False):
# lines are formatted as:
# 070161940636bab5d934af2702f4248e5a13eb29 refs/tags/ui_sandbox_acc104
# and columns are delimited with "\t"
if "refs/tags/" in line:
commit_hash, tag_ref = line.split("\t", maxsplit=1)
tag = tag_ref.replace("refs/tags/", "")
tags.append({"commit": commit_hash, "tag": tag})
# natural-sort by tag name
# flora_prod_1 < ... < flora_prod_9 > flora_prod_10
# vs lexical sort would give:
# flora_prod_1 < flora_prod_10 < ... < flora_prod_9
tags = sorted(tags, key=lambda t: [int(it) if it.isdigit() else it for it in re.split(r"(\d+)", t["tag"])])
return tags
def chunk(it, size):
it = iter(it)
sentinel = ()
return iter(lambda: tuple(itertools.islice(it, size)), sentinel)
def summarize_tags(tags: list[dict], take: int = 10) -> list[dict]:
re_prefix = re.compile(r"^(\D*)")
re_digits = re.compile(r"(\d+)")
grouped = defaultdict(list)
for t in tags:
tag_name = t["tag"]
if m := re_prefix.search(tag_name):
prefix = m.group(1)
grouped[prefix].append(t)
else:
print("no match", m)
flattened = [*grouped.pop("", [])]
for g, items in grouped.items():
sorted_items = sorted(
items, key=lambda t: [int(it) if it.isdigit() else it for it in re_digits.split(t["tag"])], reverse=True
)
flattened.extend(sorted_items[:take])
return flattened
abdus_creds = {
"username": "coder+1-at-400344683105",
"password": "4xdnGOtghKiT0M5CjulWf5raWwBSqT0Df2YkIY9Ws68=",
}
def get_commit_content():
client = boto3.client("codecommit")
res = client.get_file(
repositoryName="testing",
filePath="content.txt1",
commitSpecifier="vnext",
)
print(res)
def main():
import logging
from botocore.endpoint import Endpoint
logging.basicConfig(level=logging.INFO)
raw_make_request = Endpoint.make_request
def intercepted_make_request(*args, **kwargs):
aws_response, parsed_response = raw_make_request(*args, **kwargs)
logging.info('AWS response: %s', parsed_response)
return aws_response, parsed_response
Endpoint.make_request = intercepted_make_request
session = boto3.Session(
aws_access_key_id="AKIAQKZTNEVLBHDG5Q3X",
aws_secret_access_key="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",
region_name="eu-central-1",
)
cc = session.client("rds")
_ = cc.describe_db_clusters()
if __name__ == "__main__":
main()
exit()
# get_commit_content()
# flora b1cd47a221b84b2884b3d24198085a9f-f0dc2e747ff241649715c20d48232d8e
# oms 36363cc2f43b4cf5b1965af9f8925a4d-6deff091ce2d4c2483d8834c532a6f36
# omnitron 36363cc2f43b4cf5b1965af9f8925a4d-97400227a37940539c55489e1354ffc2
all_tags = list_repo_tags(
repository_name="b1cd47a221b84b2884b3d24198085a9f-f0dc2e747ff241649715c20d48232d8e",
username="sandbox-acc-api-user-at-023193265494",
password="sYPWKdhSx4JliXNI4ffRb4qWYBHLxA54nczSJ6CmYCY=",
region="eu-central-1",
)
print(all_tags)
exit(0)
all_tags.append({"tag": "1asd", "commit": "asdf"})
summarized = summarize_tags(all_tags, take=5)
commits = {t["commit"] for t in summarized}
session = boto3.Session(
aws_access_key_id="AKIAQKZTNEVLBHDG5Q3X",
aws_secret_access_key="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",
region_name="eu-central-1",
)
client = session.client("codecommit")
def get_commit_infos(commits: list[str]):
res = client.batch_get_commits(
repositoryName="36363cc2f43b4cf5b1965af9f8925a4d-97400227a37940539c55489e1354ffc2",
commitIds=commits,
)
return res["commits"]
with ThreadPoolExecutor() as pool:
results = list(pool.map(get_commit_infos, chunk(commits, 100)))
clone_ssh_url = repo["repositoryMetadata"]["cloneUrlSsh"]
print(repo)
exit(0)
# exit()
from botocore.awsrequest import AWSRequest
from botocore.signers import RequestSigner
# AWS Version 4 signing example
# DynamoDB API (CreateTable)
# See: http://docs.aws.amazon.com/general/latest/gr/sigv4_signing.html
# This version makes a POST request and passes request parameters
# in the body (payload) of the request. Auth information is passed in
# an Authorization header.
import sys, os, base64, datetime, hashlib, hmac
import requests # pip install requests
# ************* REQUEST VALUES *************
method = "POST"
service = "codecommit"
host = "codecommit.eu-central-1.amazonaws.com"
region = "eu-central-1"
endpoint = "https://codecommit.eu-central-1.amazonaws.com/"
# POST requests use a content type header. For DynamoDB,
# the content is JSON.
content_type = "application/x-amz-json-1.1"
# DynamoDB requires an x-amz-target header that has this format:
# DynamoDB_<API version>.<operationName>
amz_target = "CodeCommit_20150413.GetReferences"
# Request parameters for CreateTable--passed in a JSON block.
request_body = {"repositoryName": "36363cc2f43b4cf5b1965af9f8925a4d-6deff091ce2d4c2483d8834c532a6f36"}
request_parameters = json.dumps(request_body)
# Key derivation functions. See:
# http://docs.aws.amazon.com/general/latest/gr/signature-v4-examples.html#signature-v4-examples-python
def sign(key, msg):
return hmac.new(key, msg.encode("utf-8"), hashlib.sha256).digest()
def getSignatureKey(key, date_stamp, regionName, serviceName):
kDate = sign(("AWS4" + key).encode("utf-8"), date_stamp)
kRegion = sign(kDate, regionName)
kService = sign(kRegion, serviceName)
kSigning = sign(kService, "aws4_request")
return kSigning
# Read AWS access key from env. variables or configuration file. Best practice is NOT
# to embed credentials in code.
access_key = os.environ.get("AWS_ACCESS_KEY_ID", "AKIAQKZTNEVLBHDG5Q3X")
secret_key = os.environ.get("AWS_SECRET_ACCESS_KEY", "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")
if access_key is None or secret_key is None:
print("No access key is available.")
sys.exit()
# Create a date for headers and the credential string
t = datetime.datetime.utcnow()
amz_date = t.strftime("%Y%m%dT%H%M%SZ")
date_stamp = t.strftime("%Y%m%d") # Date w/o time, used in credential scope
# ************* TASK 1: CREATE A CANONICAL REQUEST *************
# http://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html
# Step 1 is to define the verb (GET, POST, etc.)--already done.
# Step 2: Create canonical URI--the part of the URI from domain to query
# string (use '/' if no path)
canonical_uri = "/"
## Step 3: Create the canonical query string. In this example, request
# parameters are passed in the body of the request and the query string
# is blank.
canonical_querystring = ""
# Step 4: Create the canonical headers. Header names must be trimmed
# and lowercase, and sorted in code point order from low to high.
# Note that there is a trailing \n.
canonical_headers = (
"content-type:"
+ content_type
+ "\n"
+ "host:"
+ host
+ "\n"
+ "x-amz-date:"
+ amz_date
+ "\n"
+ "x-amz-target:"
+ amz_target
+ "\n"
)
# Step 5: Create the list of signed headers. This lists the headers
# in the canonical_headers list, delimited with ";" and in alpha order.
# Note: The request can include any headers; canonical_headers and
# signed_headers include those that you want to be included in the
# hash of the request. "Host" and "x-amz-date" are always required.
# For DynamoDB, content-type and x-amz-target are also required.
signed_headers = "content-type;host;x-amz-date;x-amz-target"
# Step 6: Create payload hash. In this example, the payload (body of
# the request) contains the request parameters.
payload_hash = hashlib.sha256(request_parameters.encode("utf-8")).hexdigest()
# Step 7: Combine elements to create canonical request
canonical_request = (
method
+ "\n"
+ canonical_uri
+ "\n"
+ canonical_querystring
+ "\n"
+ canonical_headers
+ "\n"
+ signed_headers
+ "\n"
+ payload_hash
)
# ************* TASK 2: CREATE THE STRING TO SIGN*************
# Match the algorithm to the hashing algorithm you use, either SHA-1 or
# SHA-256 (recommended)
algorithm = "AWS4-HMAC-SHA256"
credential_scope = date_stamp + "/" + region + "/" + service + "/" + "aws4_request"
string_to_sign = (
algorithm
+ "\n"
+ amz_date
+ "\n"
+ credential_scope
+ "\n"
+ hashlib.sha256(canonical_request.encode("utf-8")).hexdigest()
)
# ************* TASK 3: CALCULATE THE SIGNATURE *************
# Create the signing key using the function defined above.
signing_key = getSignatureKey(secret_key, date_stamp, region, service)
# Sign the string_to_sign using the signing_key
signature = hmac.new(signing_key, (string_to_sign).encode("utf-8"), hashlib.sha256).hexdigest()
# ************* TASK 4: ADD SIGNING INFORMATION TO THE REQUEST *************
# Put the signature information in a header named Authorization.
authorization_header = (
algorithm
+ " "
+ "Credential="
+ access_key
+ "/"
+ credential_scope
+ ", "
+ "SignedHeaders="
+ signed_headers
+ ", "
+ "Signature="
+ signature
)
# For DynamoDB, the request can include any headers, but MUST include "host", "x-amz-date",
# "x-amz-target", "content-type", and "Authorization". Except for the authorization
# header, the headers must be included in the canonical_headers and signed_headers values, as
# noted earlier. Order here is not significant.
# # Python note: The 'host' header is added automatically by the Python 'requests' library.
headers = {
"User-Agent": "aws-sdk-js/2.627.0 promise",
"Content-Type": content_type,
"X-Amz-Date": amz_date,
"X-Amz-Target": amz_target,
"Authorization": authorization_header,
}
# ************* SEND THE REQUEST *************
print("\nBEGIN REQUEST++++++++++++++++++++++++++++++++++++")
print("Request URL = " + endpoint)
r = httpx.post(endpoint, json=request_body, headers=headers)
print("\nRESPONSE++++++++++++++++++++++++++++++++++++")
print("Response code: %d\n" % r.status_code)
print(r.text)