mirror of
https://github.com/ysoftdevs/imagepullsecret-injector.git
synced 2026-01-15 16:23:45 +01:00
Compare commits
12 Commits
imagepulls
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
13684322e9 | ||
|
|
897b4fcf7f | ||
|
|
d18923fb54 | ||
|
|
54535d9970 | ||
|
|
7980e01b83 | ||
|
|
f68a0d56d3 | ||
|
|
6f3d5cc7ef | ||
|
|
2ee7d2d62a | ||
|
|
b44e61d7d2 | ||
|
|
2f3f5e78b5 | ||
|
|
a52592033f | ||
|
|
8827431f76 |
2
.github/workflows/release-docker.yaml
vendored
2
.github/workflows/release-docker.yaml
vendored
@@ -21,7 +21,7 @@ jobs:
|
|||||||
git config user.email "$GITHUB_ACTOR@users.noreply.github.com"
|
git config user.email "$GITHUB_ACTOR@users.noreply.github.com"
|
||||||
|
|
||||||
- name: Build and push docker images (make image)
|
- name: Build and push docker images (make image)
|
||||||
run: make image
|
run: make docker-image
|
||||||
env:
|
env:
|
||||||
DOCKER_USER: ${GITHUB_ACTOR}
|
DOCKER_USER: ${GITHUB_ACTOR}
|
||||||
DOCKER_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
DOCKER_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|||||||
19
Makefile
19
Makefile
@@ -4,7 +4,6 @@
|
|||||||
REPOSITORY_BASE ?= ghcr.io
|
REPOSITORY_BASE ?= ghcr.io
|
||||||
IMAGE_REPO ?= $(REPOSITORY_BASE)/ysoftdevs/imagepullsecret-injector
|
IMAGE_REPO ?= $(REPOSITORY_BASE)/ysoftdevs/imagepullsecret-injector
|
||||||
IMAGE_NAME ?= imagepullsecret-injector
|
IMAGE_NAME ?= imagepullsecret-injector
|
||||||
GENERATOR_IMAGE_NAME ?= webhook-cert-generator
|
|
||||||
|
|
||||||
# Github host to use for checking the source tree;
|
# Github host to use for checking the source tree;
|
||||||
GIT_HOST ?= github.com/ysoftdevs
|
GIT_HOST ?= github.com/ysoftdevs
|
||||||
@@ -33,7 +32,7 @@ else
|
|||||||
$(error "This system's OS $(LOCAL_OS) isn't recognized/supported")
|
$(error "This system's OS $(LOCAL_OS) isn't recognized/supported")
|
||||||
endif
|
endif
|
||||||
|
|
||||||
all: fmt lint test build image
|
all: fmt lint test build docker-image
|
||||||
|
|
||||||
ifeq (,$(wildcard go.mod))
|
ifeq (,$(wildcard go.mod))
|
||||||
ifneq ("$(realpath $(DEST))", "$(realpath $(PWD))")
|
ifneq ("$(realpath $(DEST))", "$(realpath $(PWD))")
|
||||||
@@ -83,7 +82,7 @@ build-linux:
|
|||||||
# Containerd image section
|
# Containerd image section
|
||||||
############################################################
|
############################################################
|
||||||
|
|
||||||
containerd-image: containerd-login containerd-image containerd-image
|
containerd-image: containerd-build containerd-login containerd-push
|
||||||
|
|
||||||
containerd-login:
|
containerd-login:
|
||||||
@echo "$(DOCKER_TOKEN)" | nerdctl login -u "$(DOCKER_USER)" --password-stdin "$(REPOSITORY_BASE)"
|
@echo "$(DOCKER_TOKEN)" | nerdctl login -u "$(DOCKER_USER)" --password-stdin "$(REPOSITORY_BASE)"
|
||||||
@@ -94,25 +93,19 @@ containerd-logout:
|
|||||||
containerd-build:
|
containerd-build:
|
||||||
@echo "Building the docker image: $(IMAGE_REPO)/$(IMAGE_NAME):$(IMAGE_TAG)..."
|
@echo "Building the docker image: $(IMAGE_REPO)/$(IMAGE_NAME):$(IMAGE_TAG)..."
|
||||||
@nerdctl build -t $(IMAGE_REPO)/$(IMAGE_NAME):$(IMAGE_TAG) -f build/Dockerfile .
|
@nerdctl build -t $(IMAGE_REPO)/$(IMAGE_NAME):$(IMAGE_TAG) -f build/Dockerfile .
|
||||||
@echo "Building the docker image: $(IMAGE_REPO)/$(GENERATOR_IMAGE_NAME):$(IMAGE_TAG)..."
|
|
||||||
@nerdctl build -t $(IMAGE_REPO)/$(GENERATOR_IMAGE_NAME):$(IMAGE_TAG) -f build/Dockerfile.cert-generator .
|
|
||||||
|
|
||||||
containerd-push: containerd-build-image
|
containerd-push: containerd-build-image
|
||||||
@echo "Pushing the docker image for $(IMAGE_REPO)/$(IMAGE_NAME):$(IMAGE_TAG) and $(IMAGE_REPO)/$(IMAGE_NAME):latest..."
|
@echo "Pushing the docker image for $(IMAGE_REPO)/$(IMAGE_NAME):$(IMAGE_TAG) and $(IMAGE_REPO)/$(IMAGE_NAME):latest..."
|
||||||
@nerdctl tag $(IMAGE_REPO)/$(IMAGE_NAME):$(IMAGE_TAG) $(IMAGE_REPO)/$(IMAGE_NAME):latest
|
@nerdctl tag $(IMAGE_REPO)/$(IMAGE_NAME):$(IMAGE_TAG) $(IMAGE_REPO)/$(IMAGE_NAME):latest
|
||||||
@nerdctl push $(IMAGE_REPO)/$(IMAGE_NAME):$(IMAGE_TAG)
|
@nerdctl push $(IMAGE_REPO)/$(IMAGE_NAME):$(IMAGE_TAG)
|
||||||
@nerdctl push $(IMAGE_REPO)/$(IMAGE_NAME):latest
|
@nerdctl push $(IMAGE_REPO)/$(IMAGE_NAME):latest
|
||||||
@echo "Pushing the docker image for $(IMAGE_REPO)/$(GENERATOR_IMAGE_NAME):$(IMAGE_TAG) and $(IMAGE_REPO)/$(GENERATOR_IMAGE_NAME):latest..."
|
|
||||||
@nerdctl tag $(IMAGE_REPO)/$(GENERATOR_IMAGE_NAME):$(IMAGE_TAG) $(IMAGE_REPO)/$(GENERATOR_IMAGE_NAME):latest
|
|
||||||
@nerdctl push $(IMAGE_REPO)/$(GENERATOR_IMAGE_NAME):$(IMAGE_TAG)
|
|
||||||
@nerdctl push $(IMAGE_REPO)/$(GENERATOR_IMAGE_NAME):latest
|
|
||||||
|
|
||||||
|
|
||||||
############################################################
|
############################################################
|
||||||
# Docker image section
|
# Docker image section
|
||||||
############################################################
|
############################################################
|
||||||
|
|
||||||
docker-image: docker-login docker-build docker-push
|
docker-image: docker-build docker-login docker-push
|
||||||
|
|
||||||
docker-login:
|
docker-login:
|
||||||
@echo "$(DOCKER_TOKEN)" | docker login -u "$(DOCKER_USER)" --password-stdin "$(REPOSITORY_BASE)"
|
@echo "$(DOCKER_TOKEN)" | docker login -u "$(DOCKER_USER)" --password-stdin "$(REPOSITORY_BASE)"
|
||||||
@@ -123,18 +116,12 @@ docker-logout:
|
|||||||
docker-build:
|
docker-build:
|
||||||
@echo "Building the docker image: $(IMAGE_REPO)/$(IMAGE_NAME):$(IMAGE_TAG)..."
|
@echo "Building the docker image: $(IMAGE_REPO)/$(IMAGE_NAME):$(IMAGE_TAG)..."
|
||||||
@docker build -t $(IMAGE_REPO)/$(IMAGE_NAME):$(IMAGE_TAG) -f build/Dockerfile .
|
@docker build -t $(IMAGE_REPO)/$(IMAGE_NAME):$(IMAGE_TAG) -f build/Dockerfile .
|
||||||
@echo "Building the docker image: $(IMAGE_REPO)/$(GENERATOR_IMAGE_NAME):$(IMAGE_TAG)..."
|
|
||||||
@docker build -t $(IMAGE_REPO)/$(GENERATOR_IMAGE_NAME):$(IMAGE_TAG) -f build/Dockerfile.cert-generator .
|
|
||||||
|
|
||||||
docker-push: docker-build
|
docker-push: docker-build
|
||||||
@echo "Pushing the docker image for $(IMAGE_REPO)/$(IMAGE_NAME):$(IMAGE_TAG) and $(IMAGE_REPO)/$(IMAGE_NAME):latest..."
|
@echo "Pushing the docker image for $(IMAGE_REPO)/$(IMAGE_NAME):$(IMAGE_TAG) and $(IMAGE_REPO)/$(IMAGE_NAME):latest..."
|
||||||
@docker tag $(IMAGE_REPO)/$(IMAGE_NAME):$(IMAGE_TAG) $(IMAGE_REPO)/$(IMAGE_NAME):latest
|
@docker tag $(IMAGE_REPO)/$(IMAGE_NAME):$(IMAGE_TAG) $(IMAGE_REPO)/$(IMAGE_NAME):latest
|
||||||
@docker push $(IMAGE_REPO)/$(IMAGE_NAME):$(IMAGE_TAG)
|
@docker push $(IMAGE_REPO)/$(IMAGE_NAME):$(IMAGE_TAG)
|
||||||
@docker push $(IMAGE_REPO)/$(IMAGE_NAME):latest
|
@docker push $(IMAGE_REPO)/$(IMAGE_NAME):latest
|
||||||
@echo "Pushing the docker image for $(IMAGE_REPO)/$(GENERATOR_IMAGE_NAME):$(IMAGE_TAG) and $(IMAGE_REPO)/$(GENERATOR_IMAGE_NAME):latest..."
|
|
||||||
@docker tag $(IMAGE_REPO)/$(GENERATOR_IMAGE_NAME):$(IMAGE_TAG) $(IMAGE_REPO)/$(GENERATOR_IMAGE_NAME):latest
|
|
||||||
@docker push $(IMAGE_REPO)/$(GENERATOR_IMAGE_NAME):$(IMAGE_TAG)
|
|
||||||
@docker push $(IMAGE_REPO)/$(GENERATOR_IMAGE_NAME):latest
|
|
||||||
|
|
||||||
|
|
||||||
############################################################
|
############################################################
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
FROM golang:1.17.10 AS builder
|
FROM golang:1.19.0 AS builder
|
||||||
|
|
||||||
WORKDIR /go/src/github.com/ysoftdevs/imagepullsecret-injector
|
WORKDIR /go/src/github.com/ysoftdevs/imagepullsecret-injector
|
||||||
COPY . .
|
COPY . .
|
||||||
RUN make vendor build
|
RUN make vendor build
|
||||||
|
|
||||||
FROM alpine:3.15.4 as base
|
FROM alpine:3.16.2 as base
|
||||||
COPY --from=builder /go/src/github.com/ysoftdevs/imagepullsecret-injector/build/_output/bin/imagepullsecret-injector /usr/local/bin/imagepullsecret-injector
|
COPY --from=builder /go/src/github.com/ysoftdevs/imagepullsecret-injector/build/_output/bin/imagepullsecret-injector /usr/local/bin/imagepullsecret-injector
|
||||||
|
|
||||||
RUN addgroup -S imagepullsecret-injector-group && adduser -S imagepullsecret-injector-user -G imagepullsecret-injector-group
|
RUN addgroup -S imagepullsecret-injector-group && adduser -S imagepullsecret-injector-user -G imagepullsecret-injector-group
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
FROM alpine:3.15.4
|
|
||||||
|
|
||||||
RUN addgroup -S imagepullsecret-injector-group && adduser -S imagepullsecret-injector-user -G imagepullsecret-injector-group \
|
|
||||||
&& apk add bash curl openssl jq \
|
|
||||||
&& curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" \
|
|
||||||
&& chmod 755 ./kubectl \
|
|
||||||
&& mv ./kubectl /usr/bin/kubectl
|
|
||||||
|
|
||||||
USER imagepullsecret-injector-user
|
|
||||||
@@ -15,9 +15,9 @@ type: application
|
|||||||
# This is the chart version. This version number should be incremented each time you make changes
|
# This is the chart version. This version number should be incremented each time you make changes
|
||||||
# to the chart and its templates, including the app version.
|
# to the chart and its templates, including the app version.
|
||||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
||||||
version: 0.0.26
|
version: 0.0.29
|
||||||
|
|
||||||
# This is the version number of the application being deployed. This version number should be
|
# This is the version number of the application being deployed. This version number should be
|
||||||
# incremented each time you make changes to the application. Versions are not expected to
|
# incremented each time you make changes to the application. Versions are not expected to
|
||||||
# follow Semantic Versioning. They should reflect the version the application is using.
|
# follow Semantic Versioning. They should reflect the version the application is using.
|
||||||
appVersion: 0.0.25
|
appVersion: 0.0.26
|
||||||
|
|||||||
@@ -1,142 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
usage() {
|
|
||||||
cat <<EOF
|
|
||||||
Generate certificate suitable for use with an imagepullsecret-injector webhook service.
|
|
||||||
|
|
||||||
This script uses k8s' CertificateSigningRequest API to a generate a
|
|
||||||
certificate signed by k8s CA suitable for use with imagepullsecret-injector webhook
|
|
||||||
services. This requires permissions to create and approve CSR. See
|
|
||||||
https://kubernetes.io/docs/tasks/tls/managing-tls-in-a-cluster for
|
|
||||||
detailed explanation and additional instructions.
|
|
||||||
|
|
||||||
The server key/cert k8s CA cert are stored in a k8s secret.
|
|
||||||
|
|
||||||
usage: ${0} [OPTIONS]
|
|
||||||
|
|
||||||
The following flags are required.
|
|
||||||
|
|
||||||
--service Service name of webhook.
|
|
||||||
--namespace Namespace where webhook service and secret reside.
|
|
||||||
--secret Secret name for CA certificate and server certificate/key pair.
|
|
||||||
EOF
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
while [[ $# -gt 0 ]]; do
|
|
||||||
case ${1} in
|
|
||||||
--service)
|
|
||||||
service="$2"
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
--secret)
|
|
||||||
secret="$2"
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
--namespace)
|
|
||||||
namespace="$2"
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
usage
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
shift
|
|
||||||
done
|
|
||||||
|
|
||||||
[ -z "${service}" ] && service=ips-injector-svc
|
|
||||||
[ -z "${secret}" ] && secret=imagepullsecret-injector-webhook-certs
|
|
||||||
[ -z "${namespace}" ] && namespace=imagepullsecret-injector
|
|
||||||
|
|
||||||
if [ ! -x "$(command -v openssl)" ]; then
|
|
||||||
echo "openssl not found"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
csrName=${service}.${namespace}
|
|
||||||
tmpdir=$(mktemp -d)
|
|
||||||
echo "Creating certs in tmpdir ${tmpdir}"
|
|
||||||
|
|
||||||
cat <<EOF >> "${tmpdir}"/csr.conf
|
|
||||||
[req]
|
|
||||||
req_extensions = v3_req
|
|
||||||
distinguished_name = req_distinguished_name
|
|
||||||
[req_distinguished_name]
|
|
||||||
[ v3_req ]
|
|
||||||
basicConstraints = CA:FALSE
|
|
||||||
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
|
|
||||||
extendedKeyUsage = serverAuth
|
|
||||||
subjectAltName = @alt_names
|
|
||||||
[alt_names]
|
|
||||||
DNS.1 = ${service}
|
|
||||||
DNS.2 = ${service}.${namespace}
|
|
||||||
DNS.3 = ${service}.${namespace}.svc
|
|
||||||
EOF
|
|
||||||
|
|
||||||
openssl genrsa -out "${tmpdir}"/server-key.pem 2048
|
|
||||||
openssl req -new -key "${tmpdir}"/server-key.pem -subj "/O=system:nodes/CN=system:node:${service}.${namespace}.svc" -out "${tmpdir}"/server.csr -config "${tmpdir}"/csr.conf
|
|
||||||
|
|
||||||
# clean-up any previously created CSR for our service. Ignore errors if not present.
|
|
||||||
echo "Deleting old CertificateSigningRequests"
|
|
||||||
kubectl delete csr ${csrName} 2>/dev/null || true
|
|
||||||
|
|
||||||
echo "Creating new CertificateSigningRequests"
|
|
||||||
# create server cert/key CSR and send to k8s API
|
|
||||||
jq -n --arg request "$(< "${tmpdir}"/server.csr base64)" \
|
|
||||||
--arg namespace "$namespace" \
|
|
||||||
--arg csrName "$csrName" '{
|
|
||||||
apiVersion: "certificates.k8s.io/v1",
|
|
||||||
kind: "CertificateSigningRequest",
|
|
||||||
metadata: {
|
|
||||||
name: $csrName,
|
|
||||||
namespace: $namespace
|
|
||||||
},
|
|
||||||
spec: {
|
|
||||||
signerName: "kubernetes.io/kubelet-serving",
|
|
||||||
groups: ["system:authenticated"],
|
|
||||||
request: $request,
|
|
||||||
usages: [
|
|
||||||
"digital signature",
|
|
||||||
"key encipherment",
|
|
||||||
"server auth"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}' | kubectl create -f -
|
|
||||||
|
|
||||||
# verify CSR has been created
|
|
||||||
while true; do
|
|
||||||
if kubectl get csr ${csrName}; then
|
|
||||||
break
|
|
||||||
else
|
|
||||||
sleep 1
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "Approving CertificateSigningRequests"
|
|
||||||
# approve and fetch the signed certificate
|
|
||||||
kubectl certificate approve ${csrName}
|
|
||||||
|
|
||||||
echo "Fetching certificate from approved CertificateSigningRequests"
|
|
||||||
# verify certificate has been signed
|
|
||||||
for _ in $(seq 10); do
|
|
||||||
serverCert=$(kubectl get csr ${csrName} -o jsonpath='{.status.certificate}')
|
|
||||||
if [[ ${serverCert} != '' ]]; then
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
sleep 1
|
|
||||||
done
|
|
||||||
if [[ ${serverCert} == '' ]]; then
|
|
||||||
echo "ERROR: After approving csr ${csrName}, the signed certificate did not appear on the resource. Giving up after 10 attempts." >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
echo "${serverCert}" | openssl base64 -d -A -out "${tmpdir}"/server-cert.pem
|
|
||||||
|
|
||||||
echo "Creating secret $secret based on the retrieved certificate"
|
|
||||||
# create the secret with CA cert and server cert/key
|
|
||||||
kubectl create secret generic ${secret} \
|
|
||||||
--from-file=key.pem="${tmpdir}"/server-key.pem \
|
|
||||||
--from-file=cert.pem="${tmpdir}"/server-cert.pem \
|
|
||||||
--dry-run=client -o yaml |
|
|
||||||
kubectl -n ${namespace} apply -f -
|
|
||||||
@@ -10,18 +10,12 @@ Expand the name of the chart.
|
|||||||
ips-injector-svc
|
ips-injector-svc
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
{{- define "imagepullsecret-injector.certificateSecretName" -}}
|
{{- define "imagepullsecret-injector.certificateName" -}}
|
||||||
{{ include "imagepullsecret-injector.name" . }}-webhook-certs
|
{{ include "imagepullsecret-injector.name" . }}-webhook-cert
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
{{- define "imagepullsecret-injector.lookupCaBundle" -}}
|
{{- define "imagepullsecret-injector.certificateSecretName" -}}
|
||||||
{{- /* Find the name of the secret corresponding to the default SA in the default namespace */ -}}
|
{{ include "imagepullsecret-injector.name" . }}-webhook-certs
|
||||||
{{- /* Equivalent to `kubectl get sa -n default default -ojsonpath='{.secrets[0].name}'` */ -}}
|
|
||||||
{{- $defaultSecretName := ((lookup "v1" "ServiceAccount" "default" "default").secrets | first).name -}}
|
|
||||||
{{- /* Fetch the ca.crt from the default secret (still base64-encoded)*/ -}}
|
|
||||||
{{- /* Equivalent to `kubectl get secret -n default $defaultSecretName -ojsonpath='{.data.ca\.crt}'` */ -}}
|
|
||||||
{{- $caBundle := get (lookup "v1" "Secret" "default" $defaultSecretName ).data "ca.crt" -}}
|
|
||||||
{{- $caBundle -}}
|
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
{{/*
|
{{/*
|
||||||
|
|||||||
13
charts/imagepullsecret-injector/templates/cert.yaml
Normal file
13
charts/imagepullsecret-injector/templates/cert.yaml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
apiVersion: cert-manager.io/v1
|
||||||
|
kind: Certificate
|
||||||
|
metadata:
|
||||||
|
name: {{ include "imagepullsecret-injector.certificateName" . }}
|
||||||
|
spec:
|
||||||
|
commonName: {{ include "imagepullsecret-injector.serviceName" . }}.{{ .Release.Namespace }}.svc
|
||||||
|
dnsNames:
|
||||||
|
- {{ include "imagepullsecret-injector.serviceName" . }}.{{ .Release.Namespace }}.svc.cluster.local
|
||||||
|
- {{ include "imagepullsecret-injector.serviceName" . }}.{{ .Release.Namespace }}.svc
|
||||||
|
issuerRef:
|
||||||
|
kind: ClusterIssuer
|
||||||
|
name: {{ .Values.clusterIssuer }}
|
||||||
|
secretName: {{ include "imagepullsecret-injector.certificateSecretName" . | quote }}
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: ConfigMap
|
|
||||||
metadata:
|
|
||||||
name: imagepullsecret-injector-cert-gen-entrypoint
|
|
||||||
namespace: {{ .Release.Namespace }}
|
|
||||||
labels:
|
|
||||||
{{- include "imagepullsecret-injector.labels" . | nindent 4 }}
|
|
||||||
data:
|
|
||||||
entrypoint.sh: | {{ .Files.Get "scripts/create-signed-cert.sh" | nindent 4 }}
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
apiVersion: batch/v1beta1
|
|
||||||
kind: CronJob
|
|
||||||
metadata:
|
|
||||||
name: "{{ .Release.Name }}-cert-gen-cron-job"
|
|
||||||
labels:
|
|
||||||
{{- include "imagepullsecret-injector.labels" . | nindent 4 }}
|
|
||||||
spec:
|
|
||||||
schedule: {{ .Values.certificateGenerator.cronJobSchedule }}
|
|
||||||
jobTemplate:
|
|
||||||
metadata:
|
|
||||||
name: "{{ .Release.Name }}"
|
|
||||||
labels:
|
|
||||||
{{- include "imagepullsecret-injector.labels" . | nindent 8 }}
|
|
||||||
spec:
|
|
||||||
ttlSecondsAfterFinished: 30
|
|
||||||
template:
|
|
||||||
spec:
|
|
||||||
serviceAccountName: imagepullsecret-injector-cert-gen
|
|
||||||
restartPolicy: Never
|
|
||||||
containers:
|
|
||||||
- name: pre-install-job
|
|
||||||
image: "{{ .Values.certificateGeneratorImage.registry }}/{{ .Values.certificateGeneratorImage.repository }}:{{ .Values.certificateGeneratorImage.tag | default .Chart.AppVersion }}"
|
|
||||||
command: ["/entrypoint/entrypoint.sh"]
|
|
||||||
args:
|
|
||||||
- --service
|
|
||||||
- "{{ include "imagepullsecret-injector.serviceName" . }}"
|
|
||||||
- --namespace
|
|
||||||
- "{{ .Release.Namespace }}"
|
|
||||||
- --secret
|
|
||||||
- "{{ include "imagepullsecret-injector.certificateSecretName" . }}"
|
|
||||||
volumeMounts:
|
|
||||||
- mountPath: "/entrypoint"
|
|
||||||
name: entrypoint
|
|
||||||
volumes:
|
|
||||||
- name: entrypoint
|
|
||||||
configMap:
|
|
||||||
name: imagepullsecret-injector-cert-gen-entrypoint
|
|
||||||
items:
|
|
||||||
- key: entrypoint.sh
|
|
||||||
path: entrypoint.sh
|
|
||||||
mode: 0755
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
apiVersion: batch/v1
|
|
||||||
kind: Job
|
|
||||||
metadata:
|
|
||||||
name: "{{ .Release.Name }}-cert-gen-job-{{ .Release.Revision }}"
|
|
||||||
labels:
|
|
||||||
{{- include "imagepullsecret-injector.labels" . | nindent 4 }}
|
|
||||||
spec:
|
|
||||||
ttlSecondsAfterFinished: 30
|
|
||||||
template:
|
|
||||||
spec:
|
|
||||||
serviceAccountName: imagepullsecret-injector-cert-gen
|
|
||||||
restartPolicy: Never
|
|
||||||
containers:
|
|
||||||
- name: pre-install-job
|
|
||||||
image: "{{ .Values.certificateGeneratorImage.registry }}/{{ .Values.certificateGeneratorImage.repository }}:{{ .Values.certificateGeneratorImage.tag | default .Chart.AppVersion }}"
|
|
||||||
command: ["/entrypoint/entrypoint.sh"]
|
|
||||||
args:
|
|
||||||
- --service
|
|
||||||
- "{{ include "imagepullsecret-injector.serviceName" . }}"
|
|
||||||
- --namespace
|
|
||||||
- "{{ .Release.Namespace }}"
|
|
||||||
- --secret
|
|
||||||
- "{{ include "imagepullsecret-injector.certificateSecretName" . }}"
|
|
||||||
volumeMounts:
|
|
||||||
- mountPath: "/entrypoint"
|
|
||||||
name: entrypoint
|
|
||||||
volumes:
|
|
||||||
- name: entrypoint
|
|
||||||
configMap:
|
|
||||||
name: imagepullsecret-injector-cert-gen-entrypoint
|
|
||||||
items:
|
|
||||||
- key: entrypoint.sh
|
|
||||||
path: entrypoint.sh
|
|
||||||
mode: 0755
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: ServiceAccount
|
|
||||||
metadata:
|
|
||||||
name: imagepullsecret-injector-cert-gen
|
|
||||||
namespace : {{ .Release.Namespace }}
|
|
||||||
---
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
|
||||||
kind: ClusterRole
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
k8s-app: imagepullsecret-injector-cert-gen
|
|
||||||
name: imagepullsecret-injector-cert-gen
|
|
||||||
rules:
|
|
||||||
- apiGroups:
|
|
||||||
- ""
|
|
||||||
resources:
|
|
||||||
- secrets
|
|
||||||
- serviceaccounts
|
|
||||||
verbs:
|
|
||||||
- list
|
|
||||||
- patch
|
|
||||||
- create
|
|
||||||
- get
|
|
||||||
- delete
|
|
||||||
- apiGroups:
|
|
||||||
- ""
|
|
||||||
resources:
|
|
||||||
- namespaces
|
|
||||||
verbs:
|
|
||||||
- list
|
|
||||||
- get
|
|
||||||
- apiGroups:
|
|
||||||
- certificates.k8s.io
|
|
||||||
resources:
|
|
||||||
- certificatesigningrequests
|
|
||||||
verbs:
|
|
||||||
- create
|
|
||||||
- list
|
|
||||||
- get
|
|
||||||
- delete
|
|
||||||
- apiGroups:
|
|
||||||
- certificates.k8s.io
|
|
||||||
resources:
|
|
||||||
- certificatesigningrequests/approval
|
|
||||||
verbs:
|
|
||||||
- update
|
|
||||||
- apiGroups:
|
|
||||||
- certificates.k8s.io
|
|
||||||
resources:
|
|
||||||
- signers
|
|
||||||
resourceNames:
|
|
||||||
- kubernetes.io/kubelet-serving
|
|
||||||
verbs:
|
|
||||||
- approve
|
|
||||||
---
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
|
||||||
kind: ClusterRoleBinding
|
|
||||||
metadata:
|
|
||||||
name: imagepullsecret-injector-cert-gen
|
|
||||||
labels:
|
|
||||||
{{- include "imagepullsecret-injector.labels" . | nindent 4 }}
|
|
||||||
roleRef:
|
|
||||||
apiGroup: rbac.authorization.k8s.io
|
|
||||||
kind: ClusterRole
|
|
||||||
name: imagepullsecret-injector-cert-gen
|
|
||||||
subjects:
|
|
||||||
- kind: ServiceAccount
|
|
||||||
name: imagepullsecret-injector-cert-gen
|
|
||||||
namespace : {{ .Release.Namespace }}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: ConfigMap
|
|
||||||
metadata:
|
|
||||||
name: tmp
|
|
||||||
namespace: {{ .Release.Namespace }}
|
|
||||||
data:
|
|
||||||
caBundle: {{ include "imagepullsecret-injector.lookupCaBundle" . | quote }}
|
|
||||||
@@ -27,9 +27,9 @@ spec:
|
|||||||
- name: CONFIG_PORT
|
- name: CONFIG_PORT
|
||||||
value: "8443"
|
value: "8443"
|
||||||
- name: CONFIG_CERT_PATH
|
- name: CONFIG_CERT_PATH
|
||||||
value: "/etc/webhook/certs/cert.pem"
|
value: "/etc/webhook/certs/tls.crt"
|
||||||
- name: CONFIG_KEY_PATH
|
- name: CONFIG_KEY_PATH
|
||||||
value: "/etc/webhook/certs/key.pem"
|
value: "/etc/webhook/certs/tls.key"
|
||||||
- name: CONFIG_EXCLUDE_NAMESPACES
|
- name: CONFIG_EXCLUDE_NAMESPACES
|
||||||
value: {{ join "," .Values.imagepullsecretInjector.excludeNamespaces | quote }}
|
value: {{ join "," .Values.imagepullsecretInjector.excludeNamespaces | quote }}
|
||||||
- name: CONFIG_SERVICE_ACCOUNTS
|
- name: CONFIG_SERVICE_ACCOUNTS
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ metadata:
|
|||||||
labels:
|
labels:
|
||||||
app: imagepullsecret-injector
|
app: imagepullsecret-injector
|
||||||
{{- include "imagepullsecret-injector.labels" . | nindent 4 }}
|
{{- include "imagepullsecret-injector.labels" . | nindent 4 }}
|
||||||
|
annotations:
|
||||||
|
cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ include "imagepullsecret-injector.certificateName" . }}
|
||||||
webhooks:
|
webhooks:
|
||||||
- name: imagepullsecret-injector.ysoftdevs.github.com
|
- name: imagepullsecret-injector.ysoftdevs.github.com
|
||||||
clientConfig:
|
clientConfig:
|
||||||
@@ -13,7 +15,7 @@ webhooks:
|
|||||||
name: {{ include "imagepullsecret-injector.serviceName" . }}
|
name: {{ include "imagepullsecret-injector.serviceName" . }}
|
||||||
namespace : {{ .Release.Namespace }}
|
namespace : {{ .Release.Namespace }}
|
||||||
path: "/mutate"
|
path: "/mutate"
|
||||||
caBundle: {{ include "imagepullsecret-injector.lookupCaBundle" . }}
|
caBundle: "Cg=="
|
||||||
rules:
|
rules:
|
||||||
- operations: ["CREATE", "UPDATE"]
|
- operations: ["CREATE", "UPDATE"]
|
||||||
apiGroups: [""]
|
apiGroups: [""]
|
||||||
|
|||||||
@@ -5,11 +5,6 @@ image:
|
|||||||
# Overrides the image tag whose default is the chart appVersion.
|
# Overrides the image tag whose default is the chart appVersion.
|
||||||
tag: ""
|
tag: ""
|
||||||
|
|
||||||
certificateGeneratorImage:
|
|
||||||
registry: ghcr.io/ysoftdevs/imagepullsecret-injector
|
|
||||||
repository: webhook-cert-generator
|
|
||||||
tag: ""
|
|
||||||
|
|
||||||
imagepullsecretInjector:
|
imagepullsecretInjector:
|
||||||
dockerconfigjsonRef:
|
dockerconfigjsonRef:
|
||||||
secretName: acr-dockerconfigjson-source
|
secretName: acr-dockerconfigjson-source
|
||||||
@@ -26,4 +21,6 @@ imagepullsecretInjector:
|
|||||||
- datadog
|
- datadog
|
||||||
|
|
||||||
certificateGenerator:
|
certificateGenerator:
|
||||||
cronJobSchedule: '0 0 * * 0' # At 00:00 on Sunday
|
cronJobSchedule: '0 0 * * 0' # At 00:00 on Sunday
|
||||||
|
|
||||||
|
clusterIssuer: "webhook-issuer"
|
||||||
26
cmd/main.go
26
cmd/main.go
@@ -62,19 +62,31 @@ func main() {
|
|||||||
mux.HandleFunc("/mutate", whsvr.serve)
|
mux.HandleFunc("/mutate", whsvr.serve)
|
||||||
whsvr.server.Handler = mux
|
whsvr.server.Handler = mux
|
||||||
|
|
||||||
// start webhook server in new rountine
|
// define the channel for shutting down the main process
|
||||||
|
endSignal := make(chan bool, 1)
|
||||||
|
|
||||||
|
// wait for the system interrupts in a separate routine
|
||||||
|
go func() {
|
||||||
|
signalChan := make(chan os.Signal, 1)
|
||||||
|
signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM)
|
||||||
|
sig := <-signalChan
|
||||||
|
|
||||||
|
logger.Infof(fmt.Sprintf("Got OS signal \"%+v\", shutting down webhook server gracefully...", sig))
|
||||||
|
|
||||||
|
endSignal <- true
|
||||||
|
}()
|
||||||
|
|
||||||
|
// start the webhook server in a separate routine
|
||||||
go func() {
|
go func() {
|
||||||
if err := whsvr.server.ListenAndServeTLS(parameters.certFile, parameters.keyFile); err != nil {
|
if err := whsvr.server.ListenAndServeTLS(parameters.certFile, parameters.keyFile); err != nil {
|
||||||
logger.Errorf("Failed to listen and serve webhook server: %v", err)
|
logger.Errorf("Failed to listen and serve webhook server: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
endSignal <- true
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// listening OS shutdown singal
|
<-endSignal
|
||||||
signalChan := make(chan os.Signal, 1)
|
logger.Infof("Received the end signal, stopping the main process")
|
||||||
signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM)
|
|
||||||
<-signalChan
|
|
||||||
|
|
||||||
logger.Infof("Got OS shutdown signal, shutting down webhook server gracefully...")
|
|
||||||
if err := whsvr.Shutdown(); err != nil {
|
if err := whsvr.Shutdown(); err != nil {
|
||||||
logger.Errorf("Error while shutting down: %v", err)
|
logger.Errorf("Error while shutting down: %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
6
go.mod
6
go.mod
@@ -1,7 +1,7 @@
|
|||||||
module github.com/ysoftdevs/imagepullsecret-injector
|
module github.com/ysoftdevs/imagepullsecret-injector
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/sirupsen/logrus v1.8.1
|
github.com/sirupsen/logrus v1.9.0
|
||||||
k8s.io/api v0.24.1
|
k8s.io/api v0.24.1
|
||||||
k8s.io/apimachinery v0.24.1
|
k8s.io/apimachinery v0.24.1
|
||||||
k8s.io/client-go v0.24.1
|
k8s.io/client-go v0.24.1
|
||||||
@@ -28,7 +28,7 @@ require (
|
|||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect
|
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect
|
||||||
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect
|
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect
|
||||||
golang.org/x/sys v0.0.0-20220209214540-3681064d5158 // indirect
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
|
||||||
golang.org/x/text v0.3.7 // indirect
|
golang.org/x/text v0.3.7 // indirect
|
||||||
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect
|
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect
|
||||||
@@ -45,4 +45,4 @@ require (
|
|||||||
sigs.k8s.io/yaml v1.2.0 // indirect
|
sigs.k8s.io/yaml v1.2.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
go 1.17
|
go 1.19
|
||||||
|
|||||||
9
go.sum
9
go.sum
@@ -229,14 +229,13 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
|||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||||
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
|
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
|
||||||
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||||
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
|
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
|
||||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
|
github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||||
@@ -373,7 +372,6 @@ golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@@ -406,8 +404,9 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220209214540-3681064d5158 h1:rm+CHSpPEEW2IsXUib1ThaHIjuBVZjxNgSKmBLFfD4c=
|
|
||||||
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ=
|
||||||
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
|
|||||||
Reference in New Issue
Block a user