Skip to content
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

Windows Support #418

Draft
wants to merge 25 commits into
base: main
Choose a base branch
from
Draft
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
59 changes: 59 additions & 0 deletions .github/workflows/build-windows.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
name: Build Windows Image

on:
push:
tags:
- "*"
jobs:
build:
strategy:
fail-fast: true
matrix:
version: [2019, 2022]
runs-on: windows-${{ matrix.version }}
steps:
- uses: actions/checkout@v3
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: "1.23"
- name: Make build
run: make -f Makefile.win build
shell: bash
- name: Login to GitHub Container Registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
env:
repo: ghcr.io/saedx1/secrets-store-csi-driver-provider-aws
shell: bash
run: |
BASE_NAME=${{ env.repo }}:${{ github.ref_name }}-windows-${{ matrix.version }}
docker build . --build-arg WINDOWS_VERSION=${{ matrix.version }} -f Dockerfile.win -t ${BASE_NAME}
docker push ${BASE_NAME}

annotate:
runs-on: ubuntu-latest
needs: [build]
steps:
- name: Login to GitHub Container Registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Annotate and Push
env:
repo: ghcr.io/saedx1/secrets-store-csi-driver-provider-aws
run: |
BASE_NAME=${{ env.repo }}:${{ github.ref_name }}

docker manifest create ${BASE_NAME} ${BASE_NAME}-windows-2019 ${BASE_NAME}-windows-2022

docker manifest annotate ${BASE_NAME} ${BASE_NAME}-windows-2019 --os windows --arch amd64 --os-version 10.0.17763.4645
docker manifest annotate ${BASE_NAME} ${BASE_NAME}-windows-2022 --os windows --arch amd64 --os-version 10.0.20348.1850

docker manifest push ${BASE_NAME}
12 changes: 10 additions & 2 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,17 @@ name: Go
on: [push, pull_request]

jobs:

build:
runs-on: ubuntu-latest
strategy:
matrix:
include:
- os: windows-latest
goos: windows
- os: ubuntu-latest
goos: linux
runs-on: ${{ matrix.os }}
env:
GOOS: ${{ matrix.goos }}
steps:
- uses: actions/checkout@v3
- name: Set up Go
Expand Down
18 changes: 18 additions & 0 deletions .github/workflows/sync.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: Sync Fork

on:
schedule:
- cron: '0 14 * * *'
workflow_dispatch:

jobs:
sync:

runs-on: ubuntu-latest

steps:
- uses: tgymnich/[email protected]
with:
owner: aws
base: main
head: main
6 changes: 6 additions & 0 deletions Dockerfile.win
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
ARG WINDOWS_VERSION=2019
FROM mcr.microsoft.com/windows/nanoserver:ltsc${WINDOWS_VERSION} as base

COPY ./_output/secrets-store-csi-driver-provider-aws-amd64 /secrets-store-csi-driver-provider-aws.exe

ENTRYPOINT ["/secrets-store-csi-driver-provider-aws.exe"]
63 changes: 63 additions & 0 deletions Makefile.win
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
$(eval AWS_REGION=$(shell echo $${REGION:-us-east-1}))
$(eval REGISTRY_NAME=$(shell echo $${PRIVREPO:-public.ecr.aws/aws-secrets-manager/secrets-store-csi-driver-provider-aws}))
$(eval REPOBASE=$(shell echo $(REGISTRY_NAME) | cut -f1 -d/))

ifeq ($(REPOBASE), public.ecr.aws)
ECRCMD=ecr-public
else
ECRCMD=ecr
endif

IMAGE_NAME=secrets-store-csi-driver-provider-aws

# Build for AMD64 and ARM64
ARCHITECTURES=amd64
GOOS=windows

MAJOR_REV=1
MINOR_REV=0
$(eval PATCH_REV=$(shell git describe --always))
$(eval BUILD_DATE=$(shell date -u +%Y.%m.%d.%H.%M))
FULL_REV=$(MAJOR_REV).$(MINOR_REV).$(PATCH_REV)-$(BUILD_DATE)

LDFLAGS?="-X github.com/aws/secrets-store-csi-driver-provider-aws/server.Version=$(FULL_REV) -extldflags "-static""

CHART_RELEASER_PATH ?= cr

.PHONY: all build clean docker-login docker-buildx docker-manifest

# Build docker image and push to AWS registry
all: build docker-login docker-buildx docker-manifest

build: clean
$(foreach ARCH,$(ARCHITECTURES),CGO_ENABLED=0 GOOS=$(GOOS) GOARCH=$(ARCH) go build -a -ldflags $(LDFLAGS) -o _output/$(IMAGE_NAME)-$(ARCH) ;)

clean:
-rm -rf _output
-docker system prune --all --force

docker-login:
aws --region $(AWS_REGION) $(ECRCMD) get-login-password | docker login -u AWS --password-stdin $(REPOBASE)

# Build, tag, and push image for architecture
docker-buildx:
$(foreach ARCH,$(ARCHITECTURES),docker buildx build \
--platform $(GOOS)/$(ARCH) \
--no-cache \
--push \
-t $(REGISTRY_NAME):latest-$(ARCH) \
-t $(REGISTRY_NAME):latest-$(GOOS)-$(ARCH) \
-t $(REGISTRY_NAME):$(FULL_REV)-$(GOOS)-$(ARCH) \
. ;)

# Create and push manifest list for images
docker-manifest:
docker buildx imagetools create --tag $(REGISTRY_NAME):latest $(foreach ARCH, $(ARCHITECTURES), $(REGISTRY_NAME):latest-$(ARCH))
docker buildx imagetools create --tag $(REGISTRY_NAME):$(FULL_REV) $(foreach ARCH, $(ARCHITECTURES), $(REGISTRY_NAME):latest-$(ARCH))
docker buildx imagetools create --tag $(REGISTRY_NAME):$(MAJOR_REV) $(foreach ARCH, $(ARCHITECTURES), $(REGISTRY_NAME):latest-$(ARCH))

# Get a GitHub personal access token from the "Developer settings" section of your Github Account settings
upload-helm:
cd charts/secrets-store-csi-driver-provider-aws && ${CHART_RELEASER_PATH} package
cd charts/secrets-store-csi-driver-provider-aws && ${CHART_RELEASER_PATH} upload -o aws -r secrets-store-csi-driver-provider-aws --token $(GITHUB_TOKEN) --skip-existing
cd charts/secrets-store-csi-driver-provider-aws && ${CHART_RELEASER_PATH} index -o aws -r secrets-store-csi-driver-provider-aws --token $(GITHUB_TOKEN) --push --index-path .
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# AWS Secrets Manager and Config Provider for Secret Store CSI Driver

![badge](https://github.com/aws/secrets-store-csi-driver-provider-aws/actions/workflows/go.yml/badge.svg)
[![codecov](https://codecov.io/gh/aws/secrets-store-csi-driver-provider-aws/branch/main/graph/badge.svg?token=S7ZDTT1F8K)](https://codecov.io/gh/aws/secrets-store-csi-driver-provider-aws)
![badge](https://github.com/saedx1/secrets-store-csi-driver-provider-aws/actions/workflows/go.yml/badge.svg)

**This is an unofficial attemp to make ASCP for Secret Store CSI Driver support windows. AWS has no intention of supporting it, as a result, I created this fork. The difference is minimal between this and the original repo, and it's meant to be in-sync with the original repo at all times.**

AWS offers two services to manage secrets and parameters conveniently in your code. AWS [Secrets Manager](https://aws.amazon.com/secrets-manager/) allows you to easily rotate, manage, and retrieve database credentials, API keys, certificates, and other secrets throughout their lifecycle. AWS [Systems Manager Parameter Store](https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html) provides hierarchical storage for configuration data. The AWS provider for the [Secrets Store CSI Driver](https://github.com/kubernetes-sigs/secrets-store-csi-driver) allows you to make secrets stored in Secrets Manager and parameters stored in Parameter Store appear as files mounted in Kubernetes pods.

Expand Down
55 changes: 55 additions & 0 deletions deployment/aws-provider-installer.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,58 @@ spec:
type: DirectoryOrCreate
nodeSelector:
kubernetes.io/os: linux
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
namespace: kube-system
name: csi-secrets-store-provider-aws-windows
labels:
app: csi-secrets-store-provider-aws-windows
spec:
updateStrategy:
type: RollingUpdate
selector:
matchLabels:
app: csi-secrets-store-provider-aws-windows
template:
metadata:
labels:
app: csi-secrets-store-provider-aws-windows
spec:
serviceAccountName: csi-secrets-store-provider-aws
hostNetwork: false
containers:
- name: provider-aws-installer
image: ghcr.io/saedx1/secrets-store-csi-driver-provider-aws:1.0.0
imagePullPolicy: Always
args:
- --provider-volume=C:\k\secrets-store-csi-providers
resources:
requests:
cpu: 50m
memory: 100Mi
limits:
cpu: 50m
memory: 100Mi
securityContext:
privileged: false
allowPrivilegeEscalation: false
volumeMounts:
- mountPath: C:\k\secrets-store-csi-providers
name: providervol
- name: mountpoint-dir
mountPath: C:\var\lib\kubelet\pods
mountPropagation: HostToContainer
volumes:
- name: providervol
hostPath:
path: C:\k\secrets-store-csi-providers
- name: mountpoint-dir
hostPath:
path: C:\var\lib\kubelet\pods
type: DirectoryOrCreate
tolerations:
- operator: Exists
nodeSelector:
kubernetes.io/os: windows
7 changes: 7 additions & 0 deletions provider/secret_descriptor.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"os"
"path/filepath"
"regexp"
"runtime"
"strings"

"github.com/aws/aws-sdk-go/aws/arn"
Expand Down Expand Up @@ -101,8 +102,14 @@ func (p *SecretDescriptor) GetFileName() (path string) {
// Translate slashes to underscore if required.
if len(p.translate) != 0 {
fileName = strings.ReplaceAll(fileName, string(os.PathSeparator), p.translate)
if runtime.GOOS == "windows" {
fileName = strings.ReplaceAll(fileName, "/", p.translate)
}
} else {
fileName = strings.TrimLeft(fileName, string(os.PathSeparator)) // Strip leading slash
if runtime.GOOS == "windows" {
fileName = strings.TrimLeft(fileName, "/") // Strip leading slash
}
}

return fileName
Expand Down
32 changes: 28 additions & 4 deletions provider/secret_descriptor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package provider

import (
"fmt"
"runtime"
"strings"
"testing"
)
Expand Down Expand Up @@ -321,10 +322,19 @@ func TestGetPath(t *testing.T) {
if len(descriptorList[SSMParameter]) != 1 || len(descriptorList[SecretsManager]) != 1 {
t.Fatalf("Missing descriptors")
}
if descriptorList[SSMParameter][0].GetMountPath() != "/mountpoint/parm1" {

expectedParam := "/mountpoint/parm1"
expectedSecret := "/mountpoint/secret1"

if runtime.GOOS == "windows" {
expectedParam = "\\mountpoint\\parm1"
expectedSecret = "\\mountpoint\\secret1"
}

if descriptorList[SSMParameter][0].GetMountPath() != expectedParam {
t.Errorf("Bad mount path for SSM parameter")
}
if descriptorList[SecretsManager][0].GetMountPath() != "/mountpoint/secret1" {
if descriptorList[SecretsManager][0].GetMountPath() != expectedSecret {
t.Errorf("Bad mount path for secret")
}

Expand Down Expand Up @@ -572,7 +582,14 @@ func TestGetPathForMultiregion(t *testing.T) {
if len(descriptorList[SSMParameter]) != 1 {
t.Fatalf("Missing descriptors")
}
if descriptorList[SSMParameter][0].GetMountPath() != "/mountpoint/test" {

expected := "/mountpoint/test"

if runtime.GOOS == "windows" {
expected = "\\mountpoint\\test"
}

if descriptorList[SSMParameter][0].GetMountPath() != expected {
t.Errorf("Bad mount path for SSM parameter")
}

Expand Down Expand Up @@ -615,7 +632,14 @@ func TestVersionidsMatch(t *testing.T) {
if len(descriptorList[SSMParameter]) != 1 {
t.Fatalf("Missing descriptors")
}
if descriptorList[SSMParameter][0].GetMountPath() != "/mountpoint/test" {

expected := "/mountpoint/test"

if runtime.GOOS == "windows" {
expected = "\\mountpoint\\test"
}

if descriptorList[SSMParameter][0].GetMountPath() != expected {
t.Errorf("Bad mount path for SSM parameter")
}

Expand Down
2 changes: 2 additions & 0 deletions server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,8 @@ func (s *CSIDriverProviderServer) writeFile(secret *provider.SecretValue, mode o
return nil, err
}

tmpFile.Close()

// Swap out the old secret for the new
err = os.Rename(tmpFile.Name(), secret.Descriptor.GetMountPath())
if err != nil {
Expand Down
Loading