Skip to content

Commit 6579e84

Browse files
committed
export
0 parents  commit 6579e84

File tree

12 files changed

+578
-0
lines changed

12 files changed

+578
-0
lines changed
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
name: Build and publish package
2+
3+
on:
4+
workflow_call:
5+
inputs:
6+
tag-prefix:
7+
required: true
8+
type: string
9+
version-bump:
10+
type: string
11+
required: true
12+
default: 'minor'
13+
secrets:
14+
SONATYPE_TOKEN:
15+
required: true
16+
GPG_SECRET_KEY:
17+
required: true
18+
GPG_SECRET_KEY_ID:
19+
required: true
20+
21+
permissions:
22+
id-token: write # This is required for requesting the JWT
23+
contents: write # This is required for actions/checkout
24+
packages: write
25+
pull-requests: write
26+
27+
env:
28+
TAG_PREFIX: '${{ inputs.tag-prefix }}-'
29+
30+
jobs:
31+
buildAndPublishPackage:
32+
runs-on: ubuntu-latest
33+
steps:
34+
- uses: actions/checkout@v4
35+
with:
36+
fetch-depth: 0
37+
- uses: coursier/cache-action@v6
38+
- uses: VirtusLab/scala-cli-setup@main
39+
with:
40+
jvm: adoptium:1.21
41+
- name: Setup gpg
42+
id: gpg
43+
run: |
44+
echo "${{ secrets.GPG_SECRET_KEY }}" | base64 -d | gpg --import
45+
gpg -K
46+
- name: Configure aws credentials
47+
uses: aws-actions/configure-aws-credentials@v4
48+
with:
49+
role-to-assume: arn:aws:iam::047719648492:role/GithubActionRole
50+
role-session-name: GitHub_to_AWS_via_FederatedOIDC
51+
aws-region: eu-central-1
52+
unset-current-credentials: true
53+
- name: Get caller identity
54+
run: aws sts get-caller-identity --output json
55+
- id: version
56+
name: Compute new version
57+
run: ./scripts/computeNewVersion.sc --prefix='${{ env.TAG_PREFIX }}' --bump=${{ inputs.version-bump }} >> "$GITHUB_OUTPUT"
58+
- name: Create release bundle
59+
run: './scripts/createReleaseBundle.sc --version=${{ steps.version.outputs.new_version }} --gpg-key=${{ secrets.GPG_SECRET_KEY_ID }}'
60+
- name: Upload bundle to Sonatype
61+
run: |
62+
curl --request POST \
63+
--verbose \
64+
--header 'Authorization: Bearer ${{ secrets.SONATYPE_TOKEN }}' \
65+
--form bundle=@bundle.zip \
66+
https://central.sonatype.com/api/v1/publisher/upload?publishingType=AUTOMATIC&name=${{ env.TAG_PREFIX }}-${{ steps.version.outputs.new_version }}
67+
- name: Push tag
68+
id: tag_version
69+
uses: mathieudutour/github-tag-action@v6.1
70+
with:
71+
github_token: ${{ secrets.GITHUB_TOKEN }}
72+
custom_tag: ${{ steps.version.outputs.new_version }}
73+
tag_prefix: ${{ env.TAG_PREFIX }}
74+
- name: Create GitHub Release
75+
if: ${{ inputs.version-bump != 'keep' }}
76+
uses: actions/create-release@v1
77+
env:
78+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
79+
with:
80+
tag_name: ${{ env.TAG_PREFIX }}${{ steps.version.outputs.new_version }}
81+
release_name: ${{ inputs.tag-prefix }} release ${{ steps.version.outputs.new_version }}
82+
draft: false
83+
prerelease: false
84+
- name: Move version tag
85+
if: ${{ inputs.version-bump == 'keep' }}
86+
uses: richardsimko/update-tag@v1
87+
with:
88+
tag_name: ${{ env.TAG_PREFIX }}${{ steps.version.outputs.new_version }}
89+
env:
90+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
91+
92+

.github/workflows/release.yaml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
name: Release new package version
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
version-bump:
7+
type: choice
8+
description: 'How to bump a version?'
9+
required: true
10+
default: 'patch'
11+
options:
12+
- major
13+
- minor
14+
- patch
15+
- keep
16+
# push:
17+
# branches: [main]
18+
# paths:
19+
# - '*.scala'
20+
21+
jobs:
22+
ReleasePackage:
23+
uses: ./.github/workflows/buildAndPublishPackage.yaml
24+
secrets: inherit
25+
with:
26+
tag-prefix: 'version'
27+
version-bump: ${{ inputs.version-bump || 'patch' }}

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.bsp/
2+
.scala-build/
3+
.metals/
4+
.vscode/

.scalafmt.conf

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
version = "3.7.15"
2+
runner.dialect = scala3
3+
maxColumn = 120

LICENSE

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Copyright (c) 2024 encalmo.org
2+
3+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the " Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4+
5+
The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software.
6+
7+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

LambdaSecrets.scala

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
package org.encalmo.aws
2+
3+
import software.amazon.awssdk.auth.credentials.AwsCredentials
4+
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider
5+
import software.amazon.awssdk.auth.credentials.AwsSessionCredentials
6+
import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient
7+
import software.amazon.awssdk.regions.Region
8+
import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient
9+
import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueRequest
10+
import upickle.default.*
11+
12+
import scala.util.control.NonFatal
13+
14+
object LambdaSecrets {
15+
16+
inline def retrieveSecrets(
17+
maybeGetProperty: String => Option[String]
18+
): Map[String, String] =
19+
retrieveSecrets(maybeGetProperty, println, println)
20+
21+
def retrieveSecrets(
22+
maybeGetProperty: String => Option[String],
23+
logDebug: String => Unit,
24+
logError: String => Unit
25+
): Map[String, String] =
26+
27+
val region: Region =
28+
Region.of(maybeGetProperty("AWS_DEFAULT_REGION").getOrElse("us-east-1"))
29+
30+
val credentialsProvider = new AwsCredentialsProvider {
31+
override def resolveCredentials(): AwsCredentials =
32+
AwsSessionCredentials.create(
33+
maybeGetProperty("AWS_ACCESS_KEY_ID").getOrElse(
34+
throw new Exception(
35+
"Missing AWS_ACCESS_KEY_ID environment property"
36+
)
37+
),
38+
maybeGetProperty("AWS_SECRET_ACCESS_KEY").getOrElse(
39+
throw new Exception(
40+
"Missing AWS_SECRET_ACCESS_KEY environment property"
41+
)
42+
),
43+
maybeGetProperty("AWS_SESSION_TOKEN").getOrElse(
44+
throw new Exception(
45+
"Missing AWS_SESSION_TOKEN environment property"
46+
)
47+
)
48+
)
49+
}
50+
maybeGetProperty("ENVIRONMENT_SECRETS")
51+
.map { secretArns =>
52+
val client = SecretsManagerClient
53+
.builder()
54+
.httpClientBuilder(UrlConnectionHttpClient.builder())
55+
.credentialsProvider(credentialsProvider)
56+
.region(region)
57+
.build()
58+
try {
59+
secretArns
60+
.split(",")
61+
.map(_.trim())
62+
.map(secretArn =>
63+
logDebug(s"Looking for secrets in $secretArn ...")
64+
getSecretValueString(
65+
secretArn,
66+
client,
67+
logError
68+
)
69+
.map { secret =>
70+
val secrets = secret.readAs[Map[String, String]]
71+
logDebug(
72+
s"Retrieved ${secrets.size} secrets from $secretArn: ${secrets.keys.toSeq.sorted
73+
.mkString(", ")}"
74+
)
75+
secrets
76+
}
77+
.getOrElse {
78+
logError(
79+
s"Didn't retrieve any secrets from $secretArn"
80+
)
81+
Map.empty[String, String]
82+
}
83+
)
84+
.reduce(_ ++ _)
85+
} finally {
86+
client.close()
87+
}
88+
}
89+
.getOrElse(Map.empty[String, String])
90+
91+
private def getSecretValueString(
92+
secretId: String,
93+
client: SecretsManagerClient,
94+
logError: String => Unit
95+
): Option[String] =
96+
try {
97+
val secret = client
98+
.getSecretValue(
99+
GetSecretValueRequest.builder().secretId(secretId).build()
100+
)
101+
.secretString()
102+
Some(secret)
103+
} catch {
104+
case NonFatal(e) =>
105+
logError(e.toString())
106+
None
107+
}
108+
109+
extension (string: String) {
110+
inline def readAs[T: ReadWriter]: T =
111+
try (read(string))
112+
catch {
113+
case NonFatal(e) =>
114+
throw new Exception(e.getMessage)
115+
}
116+
}
117+
}

LambdaSecrets.test.scala

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package org.encalmo.aws
2+
3+
import scala.io.AnsiColor
4+
import scala.jdk.CollectionConverters.*
5+
6+
class LambdaSecretsSpec extends munit.FunSuite {
7+
8+
val environment = System.getenv().asScala
9+
++ Map(
10+
"ENVIRONMENT_SECRETS" -> "arn:aws:secretsmanager:eu-central-1:047719648492:secret:test-secret-rJbTad"
11+
)
12+
13+
def debug(s: String): Unit = println(s)
14+
def error(s: String): Unit = println(
15+
s"${AnsiColor.WHITE}${AnsiColor.RED_B}$s${AnsiColor.RESET}"
16+
)
17+
18+
test("retrieve test secrets") {
19+
val secrets =
20+
LambdaSecrets.retrieveSecrets(environment.get)
21+
assert(
22+
secrets.size > 0,
23+
"Retrieved secrets size should be greater than zero"
24+
)
25+
}
26+
27+
}

README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# scala-aws-secrets
2+
3+
This Scala 3 library provides a helper to access variables stored in AWS SecretsManager.
4+
5+
## Dependencies
6+
7+
- Scala >= 3.3.5
8+
- AWS SDK for Java 2.x
9+
- Scala Toolkit 0.7.0
10+
11+
## Usage
12+
13+
Use with SBT
14+
15+
libraryDependencies += "org.encalmo" %% "scala-aws-secrets" % "0.9.0"
16+
17+
or with SCALA-CLI
18+
19+
//> using dep org.encalmo::scala-aws-secrets:0.9.0
20+
21+
## Examples

project.scala

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
//> using scala 3.3.5
2+
//> using exclude scripts
3+
//> using dep "software.amazon.awssdk:regions:2.30.32,exclude=software.amazon.awssdk%apache-client,exclude=software.amazon.awssdk%netty-nio-client"
4+
//> using dep "software.amazon.awssdk:secretsmanager:2.30.32,exclude=software.amazon.awssdk%apache-client,exclude=software.amazon.awssdk%netty-nio-client"
5+
//> using dep "software.amazon.awssdk:url-connection-client:2.30.31,exclude=software.amazon.awssdk%apache-client,exclude=software.amazon.awssdk%netty-nio-client"
6+
//> using toolkit 0.7.0
7+
//> using test.dep org.scalameta::munit:1.1.0
8+
//> using publish.organization "org.encalmo"
9+
//> using publish.name "scala-aws-secrets"
10+
//> using publish.url "https://github.com/encalmo/scala-aws-secrets"
11+
//> using publish.license "MIT"
12+
//> using publish.developer "arturopala|Artur Opala|https://github.com/arturopala"
13+
//> using publish.versionControl "github:encalmo/scala-aws-secrets"
14+
//> using option -Wunused:imports -deprecation

0 commit comments

Comments
 (0)