Skip to content

Commit 850783a

Browse files
committed
adding oci-vault-get-secret-python
1 parent 8dbd8ea commit 850783a

File tree

8 files changed

+212
-0
lines changed

8 files changed

+212
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.DS_Store
2+
__pycache__
3+
test.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
# Function that retrieves a secret
2+
This function retrieves a secret from OCI Vault. The content of binary secrets are stored on the function filesystem and text secretx are returned decrypted by the function.
3+
As a best practice, we do not recommend to expose your secrets via a return value of a function. This sample just demonstrate to use OCI Vault secrets in a function.
4+
5+
As you make your way through this tutorial, look out for this icon ![user input icon](./images/userinput.png).
6+
Whenever you see it, it's time for you to perform an action.
7+
8+
9+
## Prerequisites
10+
Before you deploy this sample function, make sure you have run step A, B and C of the [Oracle Functions Quick Start Guide for Cloud Shell](https://www.oracle.com/webfolder/technetwork/tutorials/infographics/oci_functions_cloudshell_quickview/functions_quickview_top/functions_quickview/index.html)
11+
* A - Set up your tenancy
12+
* B - Create application
13+
* C - Set up your Cloud Shell dev environment
14+
15+
16+
## List Applications
17+
Assuming your have successfully completed the prerequisites, you should see your
18+
application in the list of applications.
19+
```
20+
fn ls apps
21+
```
22+
23+
24+
## Create or Update your Dynamic Group
25+
In order to use other OCI Services, your function must be part of a dynamic group. For information on how to create a dynamic group, refer to the [documentation](https://docs.cloud.oracle.com/iaas/Content/Identity/Tasks/managingdynamicgroups.htm#To).
26+
27+
When specifying the *Matching Rules*, we suggest matching all functions in a compartment with:
28+
```
29+
ALL {resource.type = 'fnfunc', resource.compartment.id = 'ocid1.compartment.oc1..aaaaaxxxxx'}
30+
```
31+
Please check the [Accessing Other Oracle Cloud Infrastructure Resources from Running Functions](https://docs.cloud.oracle.com/en-us/iaas/Content/Functions/Tasks/functionsaccessingociresources.htm) for other *Matching Rules* options.
32+
33+
34+
## Create or Update IAM Policies
35+
Create a new policy that allows the dynamic group to *use secret-family*.
36+
37+
![user input icon](./images/userinput.png)
38+
39+
Your policy should look something like this:
40+
```
41+
Allow dynamic-group <dynamic-group-name> to use secret-family in compartment <compartment-name>
42+
```
43+
For more information on how to create policies, check the [documentation](https://docs.cloud.oracle.com/iaas/Content/Identity/Concepts/policysyntax.htm).
44+
45+
46+
## Review and customize your function
47+
Review the following files in the current folder:
48+
* the code of the function, [func.py](./func.py)
49+
* its dependencies, [requirements.txt](./requirements.txt)
50+
* the function metadata, [func.yaml](./func.yaml)
51+
52+
53+
## Deploy the function
54+
In Cloud Shell, run the fn deploy command to build the function and its dependencies as a Docker image,
55+
push the image to OCIR, and deploy the function to Oracle Functions in your application.
56+
57+
![user input icon](./images/userinput.png)
58+
```
59+
fn -v deploy --app <your app name>
60+
```
61+
e.g.
62+
```
63+
fn -v deploy --app myapp
64+
```
65+
66+
67+
## Create a Vault and a Secret
68+
![user input icon](./images/userinput.png)
69+
70+
On the OCI console, navigate to *Security* > *Vault*. If you don't already have a Vault created, create one. Create a key by clicking on `Create Key`. Provide a name for the key and click `Create Key`.
71+
72+
To create a secret, click on *Create Secret* and provide a name, a description, a Vault key, the secret type (either Plain-Text or Base64), and the secret content.
73+
74+
![Create secret](./images/secret-create.png)
75+
76+
If you want to store a binary file as a secret, use the *base64* command to generate base64 code and copy/paste it as the secret content.
77+
```
78+
base64 -i ~/Downloads/cwallet.sso
79+
```
80+
81+
Click on the secret and copy its OCID
82+
83+
![Create secret](./images/secret-ocid.png)
84+
85+
86+
## Set the function configuration values
87+
The function requires the following configuration values to be set:
88+
- secret_ocid
89+
- secret_type, the value should be either "text" or "binary"
90+
91+
![user input icon](../images/userinput.png)
92+
93+
Use the *fn CLI* to set the config value:
94+
```
95+
fn config function <app-name> <function-name> secret_ocid <secret ocid value>
96+
fn config function <app-name> <function-name> secret_type <text or binary>
97+
```
98+
e.g.
99+
```
100+
fn config function myapp oci-vault-get-secret-python secret_ocid ocid1.vaultsecret.oc1.phx.xxxxxx
101+
fn config function myapp oci-vault-get-secret-python secret_type text
102+
```
103+
104+
105+
## Invoke the function
106+
Invoke the function as follows:
107+
108+
![user input icon](./images/userinput.png)
109+
```
110+
fn invoke <your app name> oci-vault-get-secret-python
111+
```
112+
e.g.:
113+
```
114+
fn invoke myapp oci-vault-get-secret-python
115+
```
116+
117+
If the secret is text and you set the function configuration key "secret_type" to "text", the function returns the content of the secret, for example:
118+
```
119+
{"secret content": "Oracle Functions rock!"}
120+
```
121+
122+
If the secret is binary data and you set the function configuration key "secret_type" to "binary", the function stores the content of the secret in a file in /tmp and returns the md5 checksum of the file, for example:
123+
```
124+
{'secret md5': 'a4269244e2eca44200bc04f83e0e4df0'}
125+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#
2+
# oci-vault-get-secret-python version 1.0.
3+
#
4+
# Copyright (c) 2020 Oracle, Inc.
5+
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
6+
#
7+
8+
import io
9+
import json
10+
import base64
11+
import oci
12+
import logging
13+
import hashlib
14+
15+
from fdk import response
16+
17+
def get_text_secret(secret_ocid):
18+
#decrypted_secret_content = ""
19+
signer = oci.auth.signers.get_resource_principals_signer()
20+
try:
21+
client = oci.secrets.SecretsClient({}, signer=signer)
22+
secret_content = client.get_secret_bundle(secret_ocid).data.secret_bundle_content.content.encode('utf-8')
23+
decrypted_secret_content = base64.b64decode(secret_content).decode("utf-8")
24+
except Exception as ex:
25+
print("ERROR: failed to retrieve the secret content", ex, flush=True)
26+
raise
27+
return {"secret content": decrypted_secret_content}
28+
29+
30+
def get_binary_secret_into_file(secret_ocid, filepath):
31+
#decrypted_secret_content = ""
32+
signer = oci.auth.signers.get_resource_principals_signer()
33+
try:
34+
client = oci.secrets.SecretsClient({}, signer=signer)
35+
secret_content = client.get_secret_bundle(secret_ocid).data.secret_bundle_content.content.encode('utf-8')
36+
except Exception as ex:
37+
print("ERROR: failed to retrieve the secret content", ex, flush=True)
38+
raise
39+
try:
40+
with open(filepath, 'wb') as secretfile:
41+
decrypted_secret_content = base64.decodebytes(secret_content)
42+
secretfile.write(decrypted_secret_content)
43+
except Exception as ex:
44+
print("ERROR: cannot write to file " + filepath, ex, flush=True)
45+
raise
46+
secret_md5 = hashlib.md5(decrypted_secret_content).hexdigest()
47+
return {"secret md5": secret_md5}
48+
49+
50+
def handler(ctx, data: io.BytesIO=None):
51+
logging.getLogger().info("function start")
52+
53+
secret_ocid = secret_type = resp = ""
54+
try:
55+
cfg = dict(ctx.Config())
56+
secret_ocid = cfg["secret_ocid"]
57+
logging.getLogger().info("Secret ocid = " + secret_ocid)
58+
secret_type = cfg["secret_type"]
59+
logging.getLogger().info("Secret type = " + secret_type)
60+
except Exception as e:
61+
print('ERROR: Missing configuration keys, secret ocid and secret_type', e, flush=True)
62+
raise
63+
64+
if secret_type == "text":
65+
resp = get_text_secret(secret_ocid)
66+
elif secret_type == "binary":
67+
resp = get_binary_secret_into_file(secret_ocid, "/tmp/secret")
68+
else:
69+
raise ValueError('the value of the configuration parameter "secret_type" has to be either "text" or "binary"')
70+
71+
logging.getLogger().info("function end")
72+
return response.Response(
73+
ctx,
74+
response_data=resp,
75+
headers={"Content-Type": "application/json"}
76+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
schema_version: 20180708
2+
name: oci-vault-get-secret-python
3+
version: 0.0.12
4+
runtime: python
5+
entrypoint: /python/bin/fdk /function/func.py handler
6+
memory: 256
Loading
Loading
Loading
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
fdk
2+
oci

0 commit comments

Comments
 (0)