mirror of
https://github.com/docker/compose.git
synced 2025-07-28 08:04:09 +02:00
use an initContainer to inject secrets as /run/secrets/xx
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
This commit is contained in:
parent
b05af0c0ac
commit
85b3cbd6ea
@ -7,6 +7,8 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/docker/ecs-plugin/pkg/amazon/cloudformation"
|
||||||
|
|
||||||
"github.com/compose-spec/compose-go/cli"
|
"github.com/compose-spec/compose-go/cli"
|
||||||
"github.com/docker/cli/cli/command"
|
"github.com/docker/cli/cli/command"
|
||||||
amazon "github.com/docker/ecs-plugin/pkg/amazon/backend"
|
amazon "github.com/docker/ecs-plugin/pkg/amazon/backend"
|
||||||
@ -59,11 +61,11 @@ func ConvertCommand(dockerCli command.Cli, options *composeOptions) *cobra.Comma
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
j, err := template.JSON()
|
json, err := cloudformation.Marshall(template)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Failed to generate JSON: %s\n", err)
|
fmt.Printf("Failed to generate JSON: %s\n", err)
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf("%s\n", string(j))
|
fmt.Printf("%s\n", string(json))
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}),
|
}),
|
||||||
|
14
ecs/go.sum
14
ecs/go.sum
@ -19,12 +19,8 @@ github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkK
|
|||||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||||
github.com/aws/aws-sdk-go v1.30.22 h1:wImJ8jQrplgmxaTeUY7FrJFn4te/VtWq+mmmJ1TnWAg=
|
|
||||||
github.com/aws/aws-sdk-go v1.30.22/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
|
|
||||||
github.com/aws/aws-sdk-go v1.33.18 h1:Ccy1SV2SsgJU3rfrD+SOhQ0jvuzfrFuja/oKI86ruPw=
|
github.com/aws/aws-sdk-go v1.33.18 h1:Ccy1SV2SsgJU3rfrD+SOhQ0jvuzfrFuja/oKI86ruPw=
|
||||||
github.com/aws/aws-sdk-go v1.33.18/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
|
github.com/aws/aws-sdk-go v1.33.18/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
|
||||||
github.com/awslabs/goformation/v4 v4.8.0 h1:UiUhyokRy3suEqBXTnipvY8klqY3Eyl4GCH17brraEc=
|
|
||||||
github.com/awslabs/goformation/v4 v4.8.0/go.mod h1:GcJULxCJfloT+3pbqCluXftdEK2AD/UqpS3hkaaBntg=
|
|
||||||
github.com/awslabs/goformation/v4 v4.14.0 h1:E2Pet9eIqA4qzt3dzzzE4YN83V4Kyfbcio0VokBC9TA=
|
github.com/awslabs/goformation/v4 v4.14.0 h1:E2Pet9eIqA4qzt3dzzzE4YN83V4Kyfbcio0VokBC9TA=
|
||||||
github.com/awslabs/goformation/v4 v4.14.0/go.mod h1:GcJULxCJfloT+3pbqCluXftdEK2AD/UqpS3hkaaBntg=
|
github.com/awslabs/goformation/v4 v4.14.0/go.mod h1:GcJULxCJfloT+3pbqCluXftdEK2AD/UqpS3hkaaBntg=
|
||||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||||
@ -58,14 +54,6 @@ github.com/cloudflare/cfssl v1.4.1 h1:vScfU2DrIUI9VPHBVeeAQ0q5A+9yshO1Gz+3QoUQiK
|
|||||||
github.com/cloudflare/cfssl v1.4.1/go.mod h1:KManx/OJPb5QY+y0+o/898AMcM128sF0bURvoVUSjTo=
|
github.com/cloudflare/cfssl v1.4.1/go.mod h1:KManx/OJPb5QY+y0+o/898AMcM128sF0bURvoVUSjTo=
|
||||||
github.com/cloudflare/go-metrics v0.0.0-20151117154305-6a9aea36fb41/go.mod h1:eaZPlJWD+G9wseg1BuRXlHnjntPMrywMsyxf+LTOdP4=
|
github.com/cloudflare/go-metrics v0.0.0-20151117154305-6a9aea36fb41/go.mod h1:eaZPlJWD+G9wseg1BuRXlHnjntPMrywMsyxf+LTOdP4=
|
||||||
github.com/cloudflare/redoctober v0.0.0-20171127175943-746a508df14c/go.mod h1:6Se34jNoqrd8bTxrmJB2Bg2aoZ2CdSXonils9NsiNgo=
|
github.com/cloudflare/redoctober v0.0.0-20171127175943-746a508df14c/go.mod h1:6Se34jNoqrd8bTxrmJB2Bg2aoZ2CdSXonils9NsiNgo=
|
||||||
github.com/compose-spec/compose-go v0.0.0-20200624120600-614475470cd8 h1:sVvKsoXizFOuJNc8dM91IeET2/zDNFj3hwHgk437iJ8=
|
|
||||||
github.com/compose-spec/compose-go v0.0.0-20200624120600-614475470cd8/go.mod h1:ih9anT8po+49hrb+1j3ldIJ/YRAaBH52ErlQLTKE2Yo=
|
|
||||||
github.com/compose-spec/compose-go v0.0.0-20200707124823-710ff8e60ad9 h1:WkFqc6UpRqxROso9KC+ceaTiXx/VWpeO1x+NV0d4d+o=
|
|
||||||
github.com/compose-spec/compose-go v0.0.0-20200707124823-710ff8e60ad9/go.mod h1:ArodJ6gsEB7iWKrbV3fSHZ08LlBvSVB0Oqg04fX86t4=
|
|
||||||
github.com/compose-spec/compose-go v0.0.0-20200709084333-492a50989a5a h1:pIiSz5jML7rQ1aupg/KHlTqCxhyXvIgeDMf4kDTzIg8=
|
|
||||||
github.com/compose-spec/compose-go v0.0.0-20200709084333-492a50989a5a/go.mod h1:ArodJ6gsEB7iWKrbV3fSHZ08LlBvSVB0Oqg04fX86t4=
|
|
||||||
github.com/compose-spec/compose-go v0.0.0-20200710075715-6fcc35384ee1 h1:F+YIkKDMHdgZBacawhFY1P9RAIgO+6uv2te6hjsjzF0=
|
|
||||||
github.com/compose-spec/compose-go v0.0.0-20200710075715-6fcc35384ee1/go.mod h1:ArodJ6gsEB7iWKrbV3fSHZ08LlBvSVB0Oqg04fX86t4=
|
|
||||||
github.com/compose-spec/compose-go v0.0.0-20200716130117-e87e4f7839e3 h1:+ntlMTrEcScJjlnEOP8P1IIrusJaR93Eazr66YgUueA=
|
github.com/compose-spec/compose-go v0.0.0-20200716130117-e87e4f7839e3 h1:+ntlMTrEcScJjlnEOP8P1IIrusJaR93Eazr66YgUueA=
|
||||||
github.com/compose-spec/compose-go v0.0.0-20200716130117-e87e4f7839e3/go.mod h1:ArodJ6gsEB7iWKrbV3fSHZ08LlBvSVB0Oqg04fX86t4=
|
github.com/compose-spec/compose-go v0.0.0-20200716130117-e87e4f7839e3/go.mod h1:ArodJ6gsEB7iWKrbV3fSHZ08LlBvSVB0Oqg04fX86t4=
|
||||||
github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko=
|
github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko=
|
||||||
@ -80,6 +68,7 @@ github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv
|
|||||||
github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0=
|
github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0=
|
||||||
github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
|
github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
|
||||||
github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc=
|
github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc=
|
||||||
|
github.com/coreos/etcd v3.3.10+incompatible h1:jFneRYjIvLMLhDLCzuTuU4rSJUjRplcJQ7pD7MnhC04=
|
||||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||||
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
|
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
|
||||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||||
@ -475,6 +464,7 @@ gotest.tools/v3 v3.0.2 h1:kG1BFyqVHuQoVQiR1bWGnfz/fmHvvuiSPIV7rvl360E=
|
|||||||
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
|
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
k8s.io/kubernetes v1.13.0 h1:qTfB+u5M92k2fCCCVP2iuhgwwSOv1EkAkvQY1tQODD8=
|
||||||
k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk=
|
k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk=
|
||||||
vbom.ml/util v0.0.0-20180919145318-efcd4e0f9787 h1:O69FD9pJA4WUZlEwYatBEEkRWKQ5cKodWpdKTrCS/iQ=
|
vbom.ml/util v0.0.0-20180919145318-efcd4e0f9787 h1:O69FD9pJA4WUZlEwYatBEEkRWKQ5cKodWpdKTrCS/iQ=
|
||||||
vbom.ml/util v0.0.0-20180919145318-efcd4e0f9787/go.mod h1:so/NYdZXCz+E3ZpW0uAoCj6uzU2+8OWDFv/HxUSs7kI=
|
vbom.ml/util v0.0.0-20180919145318-efcd4e0f9787/go.mod h1:so/NYdZXCz+E3ZpW0uAoCj6uzU2+8OWDFv/HxUSs7kI=
|
||||||
|
@ -2,9 +2,12 @@ package backend
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/awslabs/goformation/v4/cloudformation/secretsmanager"
|
||||||
|
|
||||||
ecsapi "github.com/aws/aws-sdk-go/service/ecs"
|
ecsapi "github.com/aws/aws-sdk-go/service/ecs"
|
||||||
"github.com/aws/aws-sdk-go/service/elbv2"
|
"github.com/aws/aws-sdk-go/service/elbv2"
|
||||||
cloudmapapi "github.com/aws/aws-sdk-go/service/servicediscovery"
|
cloudmapapi "github.com/aws/aws-sdk-go/service/servicediscovery"
|
||||||
@ -93,6 +96,30 @@ func (b Backend) Convert(project *types.Project) (*cloudformation.Template, erro
|
|||||||
networks[net.Name] = convertNetwork(project, net, cloudformation.Ref(ParameterVPCId), template)
|
networks[net.Name] = convertNetwork(project, net, cloudformation.Ref(ParameterVPCId), template)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for i, s := range project.Secrets {
|
||||||
|
if s.External.External {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
secret, err := ioutil.ReadFile(s.File)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
name := fmt.Sprintf("%sSecret", normalizeResourceName(s.Name))
|
||||||
|
template.Resources[name] = &secretsmanager.Secret{
|
||||||
|
Description: "",
|
||||||
|
SecretString: string(secret),
|
||||||
|
Tags: []tags.Tag{
|
||||||
|
{
|
||||||
|
Key: compose.ProjectTag,
|
||||||
|
Value: project.Name,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
s.Name = cloudformation.Ref(name)
|
||||||
|
project.Secrets[i] = s
|
||||||
|
}
|
||||||
|
|
||||||
logGroup := fmt.Sprintf("/docker-compose/%s", project.Name)
|
logGroup := fmt.Sprintf("/docker-compose/%s", project.Name)
|
||||||
template.Resources["LogGroup"] = &logs.LogGroup{
|
template.Resources["LogGroup"] = &logs.LogGroup{
|
||||||
LogGroupName: logGroup,
|
LogGroupName: logGroup,
|
||||||
|
@ -37,8 +37,14 @@ var compatibleComposeAttributes = []string{
|
|||||||
"services.ports.mode",
|
"services.ports.mode",
|
||||||
"services.ports.target",
|
"services.ports.target",
|
||||||
"services.ports.protocol",
|
"services.ports.protocol",
|
||||||
|
"services.secrets",
|
||||||
|
"services.secrets.source",
|
||||||
|
"services.secrets.target",
|
||||||
"services.user",
|
"services.user",
|
||||||
"services.working_dir",
|
"services.working_dir",
|
||||||
|
"secrets.external",
|
||||||
|
"secrets.name",
|
||||||
|
"secrets.file",
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *FargateCompatibilityChecker) CheckImage(service *types.ServiceConfig) {
|
func (c *FargateCompatibilityChecker) CheckImage(service *types.ServiceConfig) {
|
||||||
|
@ -17,6 +17,8 @@ import (
|
|||||||
"github.com/docker/ecs-plugin/pkg/compose"
|
"github.com/docker/ecs-plugin/pkg/compose"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const secretsInitContainerImage = "docker/ecs-secrets-sidecar"
|
||||||
|
|
||||||
func Convert(project *types.Project, service types.ServiceConfig) (*ecs.TaskDefinition, error) {
|
func Convert(project *types.Project, service types.ServiceConfig) (*ecs.TaskDefinition, error) {
|
||||||
cpu, mem, err := toLimits(service)
|
cpu, mem, err := toLimits(service)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -37,50 +39,118 @@ func Convert(project *types.Project, service types.ServiceConfig) (*ecs.TaskDefi
|
|||||||
fmt.Sprintf(" %s.local", project.Name),
|
fmt.Sprintf(" %s.local", project.Name),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
return &ecs.TaskDefinition{
|
logConfiguration := &ecs.TaskDefinition_LogConfiguration{
|
||||||
ContainerDefinitions: []ecs.TaskDefinition_ContainerDefinition{
|
LogDriver: ecsapi.LogDriverAwslogs,
|
||||||
{
|
Options: map[string]string{
|
||||||
Command: service.Command,
|
"awslogs-region": cloudformation.Ref("AWS::Region"),
|
||||||
DisableNetworking: service.NetworkMode == "none",
|
"awslogs-group": cloudformation.Ref("LogGroup"),
|
||||||
DnsSearchDomains: service.DNSSearch,
|
"awslogs-stream-prefix": project.Name,
|
||||||
DnsServers: service.DNS,
|
|
||||||
DockerSecurityOptions: service.SecurityOpt,
|
|
||||||
EntryPoint: service.Entrypoint,
|
|
||||||
Environment: toKeyValuePair(service.Environment),
|
|
||||||
Essential: true,
|
|
||||||
ExtraHosts: toHostEntryPtr(service.ExtraHosts),
|
|
||||||
FirelensConfiguration: nil,
|
|
||||||
HealthCheck: toHealthCheck(service.HealthCheck),
|
|
||||||
Hostname: service.Hostname,
|
|
||||||
Image: service.Image,
|
|
||||||
Interactive: false,
|
|
||||||
Links: nil,
|
|
||||||
LinuxParameters: toLinuxParameters(service),
|
|
||||||
LogConfiguration: &ecs.TaskDefinition_LogConfiguration{
|
|
||||||
LogDriver: ecsapi.LogDriverAwslogs,
|
|
||||||
Options: map[string]string{
|
|
||||||
"awslogs-region": cloudformation.Ref("AWS::Region"),
|
|
||||||
"awslogs-group": cloudformation.Ref("LogGroup"),
|
|
||||||
"awslogs-stream-prefix": project.Name,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
MemoryReservation: memReservation,
|
|
||||||
Name: service.Name,
|
|
||||||
PortMappings: toPortMappings(service.Ports),
|
|
||||||
Privileged: service.Privileged,
|
|
||||||
PseudoTerminal: service.Tty,
|
|
||||||
ReadonlyRootFilesystem: service.ReadOnly,
|
|
||||||
RepositoryCredentials: credential,
|
|
||||||
ResourceRequirements: nil,
|
|
||||||
StartTimeout: 0,
|
|
||||||
StopTimeout: durationToInt(service.StopGracePeriod),
|
|
||||||
SystemControls: toSystemControls(service.Sysctls),
|
|
||||||
Ulimits: toUlimits(service.Ulimits),
|
|
||||||
User: service.User,
|
|
||||||
VolumesFrom: nil,
|
|
||||||
WorkingDirectory: service.WorkingDir,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
containers []ecs.TaskDefinition_ContainerDefinition
|
||||||
|
volumes []ecs.TaskDefinition_Volume
|
||||||
|
mounts []ecs.TaskDefinition_MountPoint
|
||||||
|
initContainers []ecs.TaskDefinition_ContainerDependency
|
||||||
|
)
|
||||||
|
if len(service.Secrets) > 0 {
|
||||||
|
volumes = append(volumes, ecs.TaskDefinition_Volume{
|
||||||
|
Name: "secrets",
|
||||||
|
})
|
||||||
|
mounts = append(mounts, ecs.TaskDefinition_MountPoint{
|
||||||
|
ContainerPath: "/run/secrets/",
|
||||||
|
ReadOnly: true,
|
||||||
|
SourceVolume: "secrets",
|
||||||
|
})
|
||||||
|
initContainers = append(initContainers, ecs.TaskDefinition_ContainerDependency{
|
||||||
|
Condition: ecsapi.ContainerConditionSuccess,
|
||||||
|
ContainerName: "Secrets_InitContainer",
|
||||||
|
})
|
||||||
|
|
||||||
|
var (
|
||||||
|
names []string
|
||||||
|
secrets []ecs.TaskDefinition_Secret
|
||||||
|
)
|
||||||
|
for _, s := range service.Secrets {
|
||||||
|
secretConfig := project.Secrets[s.Source]
|
||||||
|
if s.Target == "" {
|
||||||
|
s.Target = s.Source
|
||||||
|
}
|
||||||
|
secrets = append(secrets, ecs.TaskDefinition_Secret{
|
||||||
|
Name: s.Target,
|
||||||
|
ValueFrom: secretConfig.Name,
|
||||||
|
})
|
||||||
|
name := s.Target
|
||||||
|
if ext, ok := secretConfig.Extensions[compose.ExtensionKeys]; ok {
|
||||||
|
var keys []string
|
||||||
|
if key, ok := ext.(string); ok {
|
||||||
|
keys = append(keys, key)
|
||||||
|
} else {
|
||||||
|
for _, k := range ext.([]interface{}) {
|
||||||
|
keys = append(keys, k.(string))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
name = fmt.Sprintf("%s:%s", s.Target, strings.Join(keys, ","))
|
||||||
|
}
|
||||||
|
names = append(names, name)
|
||||||
|
}
|
||||||
|
containers = append(containers, ecs.TaskDefinition_ContainerDefinition{
|
||||||
|
Name: fmt.Sprintf("%s_Secrets_InitContainer", normalizeResourceName(service.Name)),
|
||||||
|
Image: secretsInitContainerImage,
|
||||||
|
Command: names,
|
||||||
|
Essential: false, // FIXME this will be ignored, see https://github.com/awslabs/goformation/issues/61#issuecomment-625139607
|
||||||
|
LogConfiguration: logConfiguration,
|
||||||
|
MountPoints: []ecs.TaskDefinition_MountPoint{
|
||||||
|
{
|
||||||
|
ContainerPath: "/run/secrets/",
|
||||||
|
ReadOnly: false,
|
||||||
|
SourceVolume: "secrets",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Secrets: secrets,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
containers = append(containers, ecs.TaskDefinition_ContainerDefinition{
|
||||||
|
Command: service.Command,
|
||||||
|
DisableNetworking: service.NetworkMode == "none",
|
||||||
|
DependsOnProp: initContainers,
|
||||||
|
DnsSearchDomains: service.DNSSearch,
|
||||||
|
DnsServers: service.DNS,
|
||||||
|
DockerSecurityOptions: service.SecurityOpt,
|
||||||
|
EntryPoint: service.Entrypoint,
|
||||||
|
Environment: toKeyValuePair(service.Environment),
|
||||||
|
Essential: true,
|
||||||
|
ExtraHosts: toHostEntryPtr(service.ExtraHosts),
|
||||||
|
FirelensConfiguration: nil,
|
||||||
|
HealthCheck: toHealthCheck(service.HealthCheck),
|
||||||
|
Hostname: service.Hostname,
|
||||||
|
Image: service.Image,
|
||||||
|
Interactive: false,
|
||||||
|
Links: nil,
|
||||||
|
LinuxParameters: toLinuxParameters(service),
|
||||||
|
LogConfiguration: logConfiguration,
|
||||||
|
MemoryReservation: memReservation,
|
||||||
|
MountPoints: mounts,
|
||||||
|
Name: service.Name,
|
||||||
|
PortMappings: toPortMappings(service.Ports),
|
||||||
|
Privileged: service.Privileged,
|
||||||
|
PseudoTerminal: service.Tty,
|
||||||
|
ReadonlyRootFilesystem: service.ReadOnly,
|
||||||
|
RepositoryCredentials: credential,
|
||||||
|
ResourceRequirements: nil,
|
||||||
|
StartTimeout: 0,
|
||||||
|
StopTimeout: durationToInt(service.StopGracePeriod),
|
||||||
|
SystemControls: toSystemControls(service.Sysctls),
|
||||||
|
Ulimits: toUlimits(service.Ulimits),
|
||||||
|
User: service.User,
|
||||||
|
VolumesFrom: nil,
|
||||||
|
WorkingDirectory: service.WorkingDir,
|
||||||
|
})
|
||||||
|
|
||||||
|
return &ecs.TaskDefinition{
|
||||||
|
ContainerDefinitions: containers,
|
||||||
Cpu: cpu,
|
Cpu: cpu,
|
||||||
Family: fmt.Sprintf("%s-%s", project.Name, service.Name),
|
Family: fmt.Sprintf("%s-%s", project.Name, service.Name),
|
||||||
IpcMode: service.Ipc,
|
IpcMode: service.Ipc,
|
||||||
@ -90,6 +160,7 @@ func Convert(project *types.Project, service types.ServiceConfig) (*ecs.TaskDefi
|
|||||||
PlacementConstraints: toPlacementConstraints(service.Deploy),
|
PlacementConstraints: toPlacementConstraints(service.Deploy),
|
||||||
ProxyConfiguration: nil,
|
ProxyConfiguration: nil,
|
||||||
RequiresCompatibilities: []string{ecsapi.LaunchTypeFargate},
|
RequiresCompatibilities: []string{ecsapi.LaunchTypeFargate},
|
||||||
|
Volumes: volumes,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
45
ecs/pkg/amazon/cloudformation/marshall.go
Normal file
45
ecs/pkg/amazon/cloudformation/marshall.go
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
package cloudformation
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/awslabs/goformation/v4/cloudformation"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Marshall(template *cloudformation.Template) ([]byte, error) {
|
||||||
|
raw, err := template.JSON()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var unmarshalled interface{}
|
||||||
|
if err := json.Unmarshal(raw, &unmarshalled); err != nil {
|
||||||
|
return nil, fmt.Errorf("invalid JSON: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if input, ok := unmarshalled.(map[string]interface{}); ok {
|
||||||
|
if resources, ok := input["Resources"]; ok {
|
||||||
|
for _, uresource := range resources.(map[string]interface{}) {
|
||||||
|
if resource, ok := uresource.(map[string]interface{}); ok {
|
||||||
|
if resource["Type"] == "AWS::ECS::TaskDefinition" {
|
||||||
|
properties := resource["Properties"].(map[string]interface{})
|
||||||
|
for _, def := range properties["ContainerDefinitions"].([]interface{}) {
|
||||||
|
containerDefinition := def.(map[string]interface{})
|
||||||
|
if strings.HasSuffix(containerDefinition["Name"].(string), "_InitContainer") {
|
||||||
|
containerDefinition["Essential"] = "false"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
raw, err = json.MarshalIndent(unmarshalled, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("invalid JSON: %s", err)
|
||||||
|
}
|
||||||
|
return raw, err
|
||||||
|
}
|
@ -6,6 +6,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
cloudformation2 "github.com/docker/ecs-plugin/pkg/amazon/cloudformation"
|
||||||
|
|
||||||
"github.com/aws/aws-sdk-go/aws"
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
"github.com/aws/aws-sdk-go/aws/request"
|
"github.com/aws/aws-sdk-go/aws/request"
|
||||||
"github.com/aws/aws-sdk-go/aws/session"
|
"github.com/aws/aws-sdk-go/aws/session"
|
||||||
@ -164,7 +166,7 @@ func (s sdk) StackExists(ctx context.Context, name string) (bool, error) {
|
|||||||
|
|
||||||
func (s sdk) CreateStack(ctx context.Context, name string, template *cf.Template, parameters map[string]string) error {
|
func (s sdk) CreateStack(ctx context.Context, name string, template *cf.Template, parameters map[string]string) error {
|
||||||
logrus.Debug("Create CloudFormation stack")
|
logrus.Debug("Create CloudFormation stack")
|
||||||
json, err := template.JSON()
|
json, err := cloudformation2.Marshall(template)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -192,7 +194,7 @@ func (s sdk) CreateStack(ctx context.Context, name string, template *cf.Template
|
|||||||
|
|
||||||
func (s sdk) CreateChangeSet(ctx context.Context, name string, template *cf.Template, parameters map[string]string) (string, error) {
|
func (s sdk) CreateChangeSet(ctx context.Context, name string, template *cf.Template, parameters map[string]string) (string, error) {
|
||||||
logrus.Debug("Create CloudFormation Changeset")
|
logrus.Debug("Create CloudFormation Changeset")
|
||||||
json, err := template.JSON()
|
json, err := cloudformation2.Marshall(template)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
@ -6,4 +6,5 @@ const (
|
|||||||
ExtensionPullCredentials = "x-aws-pull_credentials"
|
ExtensionPullCredentials = "x-aws-pull_credentials"
|
||||||
ExtensionLB = "x-aws-loadbalancer"
|
ExtensionLB = "x-aws-loadbalancer"
|
||||||
ExtensionCluster = "x-aws-cluster"
|
ExtensionCluster = "x-aws-cluster"
|
||||||
|
ExtensionKeys = "x-aws-keys"
|
||||||
)
|
)
|
||||||
|
8
ecs/secrets/Dockerfile
Normal file
8
ecs/secrets/Dockerfile
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
FROM golang:1.14.4-alpine AS builder
|
||||||
|
WORKDIR $GOPATH/src/github.com/docker/ecs-secrets
|
||||||
|
COPY . .
|
||||||
|
RUN GOOS=linux GOARCH=amd64 go build -ldflags="-w -s" -o /go/bin/secrets
|
||||||
|
|
||||||
|
FROM scratch
|
||||||
|
COPY --from=builder /go/bin/secrets /secrets
|
||||||
|
ENTRYPOINT ["/secrets"]
|
85
ecs/secrets/main.go
Normal file
85
ecs/secrets/main.go
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// return codes:
|
||||||
|
// 1: failed to read secret from env
|
||||||
|
// 2: failed to parse hierarchical secret
|
||||||
|
// 3: failed to write secret content into file
|
||||||
|
func main() {
|
||||||
|
for _, name := range os.Args[1:] {
|
||||||
|
i := strings.Index(name, ":")
|
||||||
|
var keys []string
|
||||||
|
if i > 0 {
|
||||||
|
keys = strings.Split(name[i+1:], ",")
|
||||||
|
name = name[:i]
|
||||||
|
}
|
||||||
|
value, ok := os.LookupEnv(name)
|
||||||
|
if !ok {
|
||||||
|
fmt.Fprintf(os.Stderr, "%q variable not set", name)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
secrets := filepath.Join("/run/secrets", name)
|
||||||
|
|
||||||
|
if len(keys) == 0 {
|
||||||
|
// raw secret
|
||||||
|
fmt.Printf("inject secret %q info %s\n", name, secrets)
|
||||||
|
err := ioutil.WriteFile(secrets, []byte(value), 0444)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, err.Error())
|
||||||
|
os.Exit(3)
|
||||||
|
}
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
var unmarshalled interface{}
|
||||||
|
err := json.Unmarshal([]byte(value), &unmarshalled)
|
||||||
|
if err == nil {
|
||||||
|
if dict, ok := unmarshalled.(map[string]interface{}); ok {
|
||||||
|
os.MkdirAll(secrets, 0555)
|
||||||
|
for k, v := range dict {
|
||||||
|
if !contains(keys, k) && !contains(keys, "*") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
path := filepath.Join(secrets, k)
|
||||||
|
fmt.Printf("inject secret %q info %s\n", k, path)
|
||||||
|
|
||||||
|
var raw []byte
|
||||||
|
if s, ok := v.(string); ok {
|
||||||
|
raw = []byte(s)
|
||||||
|
} else {
|
||||||
|
raw, err = json.Marshal(v)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, err.Error())
|
||||||
|
os.Exit(2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = ioutil.WriteFile(path, raw, 0444)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, err.Error())
|
||||||
|
os.Exit(3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func contains(keys []string, s string) bool {
|
||||||
|
for _, k := range keys {
|
||||||
|
if k == s {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user