Compare commits

...

3 Commits

Author SHA1 Message Date
Gal Szkolnik 30ef8afca4 Merge branch 'assignment-02' 2023-07-29 04:35:10 +00:00
Gal Szkolnik 528e33a18a Assignment 02 code + documentation 2023-07-29 04:23:19 +00:00
Gal Szkolnik 180d610cb7 ASSIGNMENT-02 initial commit
VSCode generated from template
2023-07-29 04:16:12 +00:00
14 changed files with 414 additions and 2 deletions

3
.devcontainer/Dockerfile Normal file
View File

@ -0,0 +1,3 @@
# Find the Dockerfile at this URL
# https://github.com/Azure/azure-functions-docker/blob/dev/host/4/bullseye/amd64/python/python39/python39-core-tools.Dockerfile
FROM mcr.microsoft.com/azure-functions/python:4-python3.9-core-tools

View File

@ -0,0 +1,27 @@
{
"name": "Azure Functions & Python 3",
"dockerFile": "Dockerfile",
"forwardPorts": [ 7071 ],
// Configure tool-specific properties.
"customizations": {
// Configure properties specific to VS Code.
"vscode": {
// Add the IDs of extensions you want installed when the container is created.
"extensions": [
"ms-azuretools.vscode-azurefunctions",
"ms-azuretools.vscode-docker",
"ms-python.python"
]
}
},
// Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "npm install",
// Set `remoteUser` to `root` to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
"remoteUser": "vscode",
"features": {
"ghcr.io/devcontainers/features/terraform:1": {}
}
}

137
.gitignore vendored
View File

@ -1,2 +1,135 @@
data
.vscode
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
.python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that dont work, or not
# install all needed dependencies.
#Pipfile.lock
# celery beat schedule file
celerybeat-schedule
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# Azure Functions artifacts
bin
obj
appsettings.json
local.settings.json
# Azurite artifacts
__blobstorage__
__queuestorage__
__azurite_db*__.json
.python_packages

5
.npmignore Normal file
View File

@ -0,0 +1,5 @@
README.md
test-project
definition-manifest.json
.vscode
.npmignore

6
.vscode/extensions.json vendored Normal file
View File

@ -0,0 +1,6 @@
{
"recommendations": [
"ms-azuretools.vscode-azurefunctions",
"ms-python.python"
]
}

12
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,12 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Attach to Python Functions",
"type": "python",
"request": "attach",
"port": 9091,
"preLaunchTask": "func: host start"
}
]
}

8
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,8 @@
{
"azureFunctions.deploySubpath": "src/ASSIGNMENT-02",
"azureFunctions.scmDoBuildDuringDeployment": true,
"azureFunctions.pythonVenv": ".venv",
"azureFunctions.projectLanguage": "Python",
"azureFunctions.projectRuntime": "~4",
"azureFunctions.projectSubpath": "src/ASSIGNMENT-02"
}

33
.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,33 @@
{
"version": "2.0.0",
"tasks": [
{
"type": "func",
"label": "func: host start",
"command": "host start",
"problemMatcher": "$func-python-watch",
"isBackground": true,
"dependsOn": "pip install (functions)",
"options": {
"cwd": "${workspaceFolder}/src/ASSIGNMENT-02"
}
},
{
"label": "pip install (functions)",
"type": "shell",
"osx": {
"command": "${config:azureFunctions.pythonVenv}/bin/python -m pip install -r requirements.txt"
},
"windows": {
"command": "${config:azureFunctions.pythonVenv}/Scripts/python -m pip install -r requirements.txt"
},
"linux": {
"command": "${config:azureFunctions.pythonVenv}/bin/python -m pip install -r requirements.txt"
},
"problemMatcher": [],
"options": {
"cwd": "${workspaceFolder}/src/ASSIGNMENT-02"
}
}
]
}

View File

@ -0,0 +1,59 @@
# 2nd Assignment
## Main Challanges
Azure is a new envionrment for me, but my experience within GCP has been
helpful in navigating my needs.
I've never deployed function apps before (not even in GCP), but the
concept was rather clear to me.
I learned how to creat a System Assigned Managed Role to the azure func.
I also learned how to assign it to the Key Valult's Secret-User roles.
(I did this manually on each vault, as the free account does not allow
creation of custom roles, which is probably what I would use in a
production envrionment)
I learned how to allow Visual Studio to create the function app and
deploy the code. Something I had to troubleshoot at first, as my first
setup failed to deploy multiple times.
Seems that newbies to this realm, based on my searching for solutions,
face similar issues - but I eventually overcame those hurdles by
correctly deploying a fresh Funciton App.
## Script logic
The script itself is rather simple, I based it on the template HTTP
trigger function from the VS Code template.
I added authentication and the KeyVault logic, and added error handling
and reporting code.
After a successful local run, I created a requirements.txt file and
deploeyd the function app to Azure.
### Notes about current implementation
In a production public (without authentication of any sorts) facing page
I would not leave the error reporting code as it is, and rely more on
logging, but since I'm unfamiliar with the logging constructs preferred
I ommitted this at this time.
## How to use:
The App's URL is:
> <https://anysecrets.azurewebsites.net/api/getsecret>
It takes a single argument `name` which is the Vault's name to pull the
secret from (GSzVaronisAssignmentKv1, GSzVaronisAssignmentKv2 or
GSzVaronisAssignmentKv3)
For example:
> <https://anysecrets.azurewebsites.net/api/getsecret?name=GSzVaronisAssignmentKv2>
When name is not supplied, some identifying details are presented for
troubleshooting purposes.
When an exception occured, the error message will be printed.

View File

@ -0,0 +1,73 @@
import logging
import sys
# Code based on VSCode template for Python Azure Function Apps and
# https://learn.microsoft.com/en-us/azure/key-vault/secrets/quick-create-python?tabs=azure-cli#create-the-sample-code
import os
import azure.functions as func
from azure.keyvault.secrets import SecretClient
from azure.identity import DefaultAzureCredential
def main(req: func.HttpRequest) -> func.HttpResponse:
logging.info('Python HTTP trigger function processed a request.')
name = req.params.get('name')
credential = None
Err = None
msg = ""
status_code = 200
if not name:
status_code = 201
try:
req_body = req.get_json()
except ValueError:
pass
else:
name = req_body.get('name')
try:
credential = DefaultAzureCredential()
except:
the_type, Err, the_traceback = sys.exc_info()
status_code = 500
credential = None
pass
# except BaseException as e:
# return func.HttpResponse( e, status_code=200 )
# credentialErr = e
if name and credential:
keyVaultName = name
KVUri = f"https://{keyVaultName}.vault.azure.net"
try:
client = SecretClient(vault_url=KVUri, credential=credential)
secretName = "VaronisAssignmentSecret"
print(f"Retrieving your secret from {keyVaultName}.")
retrieved_secret = client.get_secret(secretName)
print(f"Your secret is '{retrieved_secret.value}'.")
msg = f"{retrieved_secret.value}"
except:
status_code = 500
the_type, Err, the_traceback = sys.exc_info()
pass
else:
msg = "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response."
if status_code != 200:
if credential:
msg += f"\nCredentials { credential }."
if Err:
msg += f"\nErr: { Err }"
return func.HttpResponse( msg, status_code=status_code )

View File

@ -0,0 +1,20 @@
{
"scriptFile": "__init__.py",
"bindings": [
{
"authLevel": "anonymous",
"type": "httpTrigger",
"direction": "in",
"name": "req",
"methods": [
"get",
"post"
]
},
{
"type": "http",
"direction": "out",
"name": "$return"
}
]
}

View File

@ -0,0 +1,3 @@
{
"name": "GSzVaronisAssignmentKv1"
}

View File

@ -0,0 +1,7 @@
{
"version": "2.0",
"extensionBundle": {
"id": "Microsoft.Azure.Functions.ExtensionBundle",
"version": "[3.*, 4.0.0)"
}
}

View File

@ -0,0 +1,23 @@
azure-common==1.1.28
azure-core==1.28.0
azure-functions==1.15.0
azure-identity==1.13.0
azure-keyvault==4.2.0
azure-keyvault-certificates==4.7.0
azure-keyvault-keys==4.8.0
azure-keyvault-secrets==4.7.0
certifi==2023.7.22
cffi==1.15.1
charset-normalizer==3.2.0
cryptography==41.0.2
idna==3.4
isodate==0.6.1
msal==1.23.0
msal-extensions==1.0.0
portalocker==2.7.0
pycparser==2.21
PyJWT==2.8.0
requests==2.31.0
six==1.16.0
typing_extensions==4.7.1
urllib3==2.0.4