Skip to content

added dotnet function for deciphering using using vault key #12

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ This repository provides examples demonstrating how to use Oracle Functions.
| Run a SQL statement against Autonomous DB using DB Client |[sample](./samples/oci-adb-client-runsql-python)||
| Publish a notification using ONS |[sample](./samples/oci-ons-publish-python)|
| Send an email using Email Delivery Service |[sample](./samples/oci-email-send-python)|
| Decrypt cipher using Vault keys |[sample](./samples/oci-vault-decrypt-python)
| Decrypt cipher using Vault keys |[sample](./samples/oci-vault-decrypt-python)||[sample](./samples/oci-vault-decrypt-dotnet)|
| Get a secret from Vault |[sample](./samples/oci-vault-get-secret-python)||[sample](./samples/oci-vault-get-secret-dotnet)|
| Write IAM policies that enables Functions in a tenancy to access resources in other tenancies ||[sample](./samples/oci-cross-tenancy-policies-java)
| Trace a function with APM and add custom child spans using Zipkin |[sample](./samples/trace-functions-with-apm)|
Expand Down
30 changes: 30 additions & 0 deletions samples/oci-vault-decrypt-dotnet/Common/KmsCryptoClientHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@

using System;
using System.Threading.Tasks;
using System.Text;

using Oci.Common;
using Oci.Common.Auth;
using Oci.KeymanagementService;


namespace VaultDecrypt
{
public class KmsCryptoClientHelper
{
public static KmsCryptoClient GetVaultDecryptClient(string crypto_endpoint)
{
try
{
return new KmsCryptoClient(ResourcePrincipalAuthenticationDetailsProvider.GetProvider(), new ClientConfiguration(), crypto_endpoint);
}
catch (Exception ex)
{
Console.WriteLine("Unable To Create Resource Principal Provider: {0}", ex.Message);
Console.WriteLine("Defaulting to Instance Provider");
return new KmsCryptoClient(new InstancePrincipalsAuthenticationDetailsProvider(), new ClientConfiguration(), crypto_endpoint);
}
}

}
}
59 changes: 59 additions & 0 deletions samples/oci-vault-decrypt-dotnet/Controller/GetSecretsHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@

using System;
using System.Threading.Tasks;
using System.Text;
using System.Collections.Generic;
using System.IO;
using Oci.Common.Model;
using Oci.Common;
using Oci.Common.Auth;
using Oci.KeymanagementService;
using Oci.KeymanagementService.Models;
using Oci.KeymanagementService.Requests;
using Oci.KeymanagementService.Responses;


namespace VaultDecrypt
{
public class GetSecretsHelper
{
public static async Task<string> getSecretValue(KmsCryptoClient client, string vault_key_ocid, string cipher)

{

try
{


// Create a request and dependent object(s).
var decryptDataDetails = new Oci.KeymanagementService.Models.DecryptDataDetails
{
Ciphertext = cipher,
KeyId = vault_key_ocid,
};

var decryptRequest = new Oci.KeymanagementService.Requests.DecryptRequest
{
DecryptDataDetails = decryptDataDetails,
};


var response = await client.Decrypt(decryptRequest);
var value_b64 = response.DecryptedData.Plaintext;
byte[] secretValueDecoded = Convert.FromBase64String(value_b64);
string secretIdValue = Encoding.Default.GetString(secretValueDecoded);
return secretIdValue;

}

catch (OciException ex)
{
Console.WriteLine("Unable To Get Secret : {0}", ex.Message);
return "Failed " + ex.Message;
}

}


}
}
11 changes: 11 additions & 0 deletions samples/oci-vault-decrypt-dotnet/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
FROM fnproject/dotnet:3.1-1.0.4-dev as build-stage
WORKDIR /function
COPY . .
RUN dotnet sln add VaultDecrypt.csproj
RUN dotnet build VaultDecrypt.csproj -c Release
RUN dotnet publish VaultDecrypt.csproj -c Release -o out
FROM fnproject/dotnet:3.1-1.0.4
WORKDIR /function
COPY --from=build-stage /function/out/ /function/
ENTRYPOINT ["dotnet", "VaultDecrypt.dll"]
CMD ["VaultDecrypt:Function:function_handler"]
17 changes: 17 additions & 0 deletions samples/oci-vault-decrypt-dotnet/Function.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26124.0
MinimumVisualStudioVersion = 15.0.26124.0
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
13 changes: 13 additions & 0 deletions samples/oci-vault-decrypt-dotnet/Models/InputMessage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System;

namespace VaultDecrypt
{

class InputMessage
{
public string cipher { get; set; }


}

}
14 changes: 14 additions & 0 deletions samples/oci-vault-decrypt-dotnet/Models/SecretContent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System;

namespace VaultDecrypt
{

class SecretContent
{

public string secret_content { get; set; }


}

}
130 changes: 130 additions & 0 deletions samples/oci-vault-decrypt-dotnet/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
# Function that decrypts a cipher text using Vault keys
This function decrypts a cipher text using a Vault key. 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 Vault keys in a function.

As you make your way through this tutorial, look out for this icon ![user input icon](./images/userinput.png).
Whenever you see it, it's time for you to perform an action.


## Prerequisites
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)
* A - Set up your tenancy
* B - Create application
* C - Set up your Cloud Shell dev environment


## List Applications
Assuming your have successfully completed the prerequisites, you should see your
application in the list of applications.
```
fn ls apps
```


## Create or Update your Dynamic Group
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).

When specifying the *Matching Rules*, we suggest matching all functions in a compartment with:
```
ALL {resource.type = 'fnfunc', resource.compartment.id = 'ocid1.compartment.oc1..aaaaaxxxxx'}
```
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.


## Create or Update IAM Policies
Create a new policy that allows the dynamic group to manage compute instances. We will grant `use` access to `keys` in the compartment.

![user input icon](./images/userinput.png)

Your policy should look something like this:
```
Allow dynamic-group <dynamic-group-name> to use keys in compartment <compartment-name>
```

For more information on how to create policies, check the [documentation](https://docs.cloud.oracle.com/iaas/Content/Identity/Concepts/policysyntax.htm).


## Review and customize the function
Review the following files in the current folder:
* the code of the function, [VaultDecrypt.cs](./VaultDecrypt.cs)
* its dependencies, [VaultDecrypt.csproj](./VaultDecrypt.csproj)
* the function metadata, [func.yaml](./func.yaml)


## Deploy the function
In Cloud Shell, run the *fn deploy* command to build the function and its dependencies as a Docker image,
push the image to OCIR, and deploy the function to Oracle Functions in your application.

![user input icon](./images/userinput.png)
```
fn -v deploy --app <app-name>
```


## Create the Vault key and a cipher text
![user input icon](./images/userinput.png)

On the OCI console, navigate to *Security* > *Key Management*. 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`.

In your vault, note the *Cryptographic Endpoint* and your key OCID.

![Cryptographic Endpoint anf Key OCID](./images/vault.png)

Set the `KEY_OCID` and `CRYPTOGRAPHIC_ENDPOINTT` environement variables with the OCID of your Vault key and the Vault Endpoint. For example:
```
KEY_OCID='ocid1.key.oc1.phx.acdfdfna.abyxxxxxxxsqhycfq'
CRYPTOGRAPHIC_ENDPOINT='https://a5pdddfdfna-crypto.kms.us-phoenix-1.oraclecloud.com'
```

Set the `PLAIN_TEXT` environement variable with the text you will encrypt:
```
PLAIN_TEXT="my text"
```
Run the following command to get the encrypted version of your text:
```
oci kms crypto encrypt --key-id "$KEY_OCID" --endpoint "$CRYPTOGRAPHIC_ENDPOINT" \
--plaintext "$( echo -n $PLAIN_TEXT | base64 -b0 )" | jq -r .data.ciphertext
```
The above command is for MacOS. For Linux, replace `base64 -b0` with `base64 -w0`.

The command returns a Cipher text, you will use it to invoke your function.


## Set the function configuration values
The function requires the following configuration values to be set:
- key_ocid
- cryptographic_endpoint

![user input icon](./images/userinput.png)

Use the *fn CLI* to set the config value:
```
fn config function <app-name> <function-name> key_ocid <Vault-key-OCID>
fn config function <app-name> <function-name> cryptographic_endpoint <Vault-Cryptographic-Endpoint>
```
e.g.
```
fn config function myapp oci-vault-decrypt-dotnet key_ocid "ocid1.key.oc1.phx.a5pedhchaafna.abyhqljt63augu4nwptqrvaw7gymh7zp7ihvgayo72pehd3sqhfproiaycfq"
fn config function myapp oci-vault-decrypt-dotnet cryptographic_endpoint 'https://a5pedhchaafna-crypto.kms.us-phoenix-1.oraclecloud.com'
```


## Invoke the function
The function requires the cipher to be specified in the payload to be invoked. "cipher-text" is encrypted text you generated in the section [Create the Vault key and a cipher text](#Create the Vault key and a cipher text)

![user input icon](./images/userinput.png)
```
echo '{"cipher": "<cipher-text>"}' | fn invoke <app-name> oci-vault-decrypt-dotnet
```
e.g.:
```
echo '{"cipher": "Ia+hS8+UYAEV8gr00ItHxsC1jhfslbzAA="}' | fn invoke myapp oci-vault-decrypt-dotnet
```

Upon success, the function should return the decrypted text:
{"secret_content":[{"secret_content":"my text"}]}


## Monitoring Functions

Learn how to configure basic observability for your function using metrics, alarms and email alerts:
* [Basic Guidance for Monitoring your Functions](../basic-observability/functions.md)
42 changes: 42 additions & 0 deletions samples/oci-vault-decrypt-dotnet/VaultDecrypt.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using Fnproject.Fn.Fdk;
using System.Runtime.CompilerServices;
using System.Collections.Generic;
using System;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using Oci.KeymanagementService;
using Oci.KeymanagementService.Models;

namespace VaultDecrypt
{
class Function
{
public string function_handler(InputMessage input)
{

Dictionary<string, List<SecretContent>> output = new Dictionary<string, List<SecretContent>>();
var secret_details_list = new List<SecretContent>();

string cipher = input.cipher;
string vault_key_ocid = Environment.GetEnvironmentVariable("key_ocid");
string crypto_endpoint = Environment.GetEnvironmentVariable("cryptographic_endpoint");


KmsCryptoClient client = KmsCryptoClientHelper.GetVaultDecryptClient(crypto_endpoint);

Task<string> secret_value = GetSecretsHelper.getSecretValue(client, vault_key_ocid, cipher);

var secret_detail = new SecretContent();
secret_detail.secret_content = secret_value.Result;
secret_details_list.Add(secret_detail);

output.Add("secret_content", secret_details_list);
return System.Text.Json.JsonSerializer.Serialize(output);

}

static void Main(string[] args) { Fdk.Handle(args[0]); }

}
}
17 changes: 17 additions & 0 deletions samples/oci-vault-decrypt-dotnet/VaultDecrypt.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Fnproject.Fn.Fdk" Version="1.0.4" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="OCI.DotNetSDK.Common" Version="42.1.0" />
<PackageReference Include="OCI.DotNetSDK.Keymanagement" Version="42.1.0" />
</ItemGroup>

</Project>
8 changes: 8 additions & 0 deletions samples/oci-vault-decrypt-dotnet/func.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
schema_version: 20180708
name: oci-vault-decrypt-dotnet
version: 0.0.90
runtime: dotnet3.1
build_image: fnproject/dotnet:3.1-1.0.4-dev
run_image: fnproject/dotnet:3.1-1.0.4
cmd: VaultDecrypt:Function:function_handler
entrypoint: dotnet VaultDecrypt.dll
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.