Skip to content

Commit b9c076f

Browse files
cylithaJeztah
authored andcommitted
Allow the external CAs to be removed entirely using the CL
Allow setting --external-ca to an empty string, to allow for removing all external CAs entirely. This will help for instance if rotating from a fully external CA to an internal CA (if the CA's cert and key are already in the swarm for instance). Signed-off-by: Ying Li <ying.li@docker.com> Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
1 parent 2ea4dc1 commit b9c076f

2 files changed

Lines changed: 104 additions & 21 deletions

File tree

cli/command/swarm/opts.go

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"encoding/pem"
66
"errors"
77
"fmt"
8+
"io"
89
"os"
910
"strings"
1011
"time"
@@ -99,7 +100,9 @@ func (m *ExternalCAOption) Set(value string) error {
99100
return err
100101
}
101102

102-
m.values = append(m.values, parsed)
103+
if parsed != nil {
104+
m.values = append(m.values, parsed)
105+
}
103106
return nil
104107
}
105108

@@ -112,8 +115,10 @@ func (*ExternalCAOption) Type() string {
112115
func (m *ExternalCAOption) String() string {
113116
externalCAs := make([]string, 0, len(m.values))
114117
for _, externalCA := range m.values {
115-
repr := fmt.Sprintf("%s: %s", externalCA.Protocol, externalCA.URL)
116-
externalCAs = append(externalCAs, repr)
118+
if externalCA != nil {
119+
repr := fmt.Sprintf("%s: %s", externalCA.Protocol, externalCA.URL)
120+
externalCAs = append(externalCAs, repr)
121+
}
117122
}
118123
return strings.Join(externalCAs, ", ")
119124
}
@@ -161,6 +166,9 @@ func (p *PEMFile) Contents() string {
161166
func parseExternalCA(caSpec string) (*swarm.ExternalCA, error) {
162167
csvReader := csv.NewReader(strings.NewReader(caSpec))
163168
fields, err := csvReader.Read()
169+
if err == io.EOF {
170+
return nil, nil
171+
}
164172
if err != nil {
165173
return nil, err
166174
}

cli/command/swarm/opts_test.go

Lines changed: 93 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package swarm
33
import (
44
"testing"
55

6+
"github.com/moby/moby/api/types/swarm"
67
"gotest.tools/v3/assert"
78
is "gotest.tools/v3/assert/cmp"
89
)
@@ -42,10 +43,6 @@ func TestExternalCAOptionErrors(t *testing.T) {
4243
externalCA string
4344
expectedError string
4445
}{
45-
{
46-
externalCA: "",
47-
expectedError: "EOF",
48-
},
4946
{
5047
externalCA: "anything",
5148
expectedError: "invalid field 'anything' must be a key=value pair",
@@ -71,34 +68,112 @@ func TestExternalCAOptionErrors(t *testing.T) {
7168

7269
func TestExternalCAOption(t *testing.T) {
7370
testCases := []struct {
74-
externalCA string
75-
expected string
71+
externalCAs []string
72+
expected []*swarm.ExternalCA
73+
expectedString string
7674
}{
7775
{
78-
externalCA: "protocol=cfssl,url=anything",
79-
expected: "cfssl: anything",
76+
externalCAs: []string{""},
77+
expected: nil,
78+
expectedString: "",
79+
},
80+
{
81+
externalCAs: []string{"protocol=cfssl,url=anything"},
82+
expected: []*swarm.ExternalCA{
83+
{
84+
Protocol: swarm.ExternalCAProtocolCFSSL,
85+
URL: "anything",
86+
Options: make(map[string]string),
87+
},
88+
},
89+
expectedString: "cfssl: anything",
90+
},
91+
{
92+
externalCAs: []string{"protocol=CFSSL,url=anything"},
93+
expected: []*swarm.ExternalCA{
94+
{
95+
Protocol: swarm.ExternalCAProtocolCFSSL,
96+
URL: "anything",
97+
Options: make(map[string]string),
98+
},
99+
},
100+
expectedString: "cfssl: anything",
101+
},
102+
{
103+
externalCAs: []string{"protocol=Cfssl,url=https://example.com"},
104+
expected: []*swarm.ExternalCA{
105+
{
106+
Protocol: swarm.ExternalCAProtocolCFSSL,
107+
URL: "https://example.com",
108+
Options: make(map[string]string),
109+
},
110+
},
111+
expectedString: "cfssl: https://example.com",
80112
},
81113
{
82-
externalCA: "protocol=CFSSL,url=anything",
83-
expected: "cfssl: anything",
114+
externalCAs: []string{"protocol=Cfssl,url=https://example.com,foo=bar"},
115+
expected: []*swarm.ExternalCA{
116+
{
117+
Protocol: swarm.ExternalCAProtocolCFSSL,
118+
URL: "https://example.com",
119+
Options: map[string]string{
120+
"foo": "bar",
121+
},
122+
},
123+
},
124+
expectedString: "cfssl: https://example.com",
84125
},
85126
{
86-
externalCA: "protocol=Cfssl,url=https://example.com",
87-
expected: "cfssl: https://example.com",
127+
externalCAs: []string{"protocol=Cfssl,url=https://example.com,foo=bar,foo=baz"},
128+
expected: []*swarm.ExternalCA{
129+
{
130+
Protocol: swarm.ExternalCAProtocolCFSSL,
131+
URL: "https://example.com",
132+
Options: map[string]string{
133+
"foo": "baz",
134+
},
135+
},
136+
},
137+
expectedString: "cfssl: https://example.com",
88138
},
89139
{
90-
externalCA: "protocol=Cfssl,url=https://example.com,foo=bar",
91-
expected: "cfssl: https://example.com",
140+
externalCAs: []string{"", "protocol=Cfssl,url=https://example.com"},
141+
expected: []*swarm.ExternalCA{
142+
{
143+
Protocol: swarm.ExternalCAProtocolCFSSL,
144+
URL: "https://example.com",
145+
Options: make(map[string]string),
146+
},
147+
},
148+
expectedString: "cfssl: https://example.com",
92149
},
93150
{
94-
externalCA: "protocol=Cfssl,url=https://example.com,foo=bar,foo=baz",
95-
expected: "cfssl: https://example.com",
151+
externalCAs: []string{
152+
"protocol=Cfssl,url=https://example.com",
153+
"protocol=Cfssl,url=https://example2.com",
154+
},
155+
expected: []*swarm.ExternalCA{
156+
{
157+
Protocol: swarm.ExternalCAProtocolCFSSL,
158+
URL: "https://example.com",
159+
Options: make(map[string]string),
160+
},
161+
{
162+
Protocol: swarm.ExternalCAProtocolCFSSL,
163+
URL: "https://example2.com",
164+
Options: make(map[string]string),
165+
},
166+
},
167+
expectedString: "cfssl: https://example.com, cfssl: https://example2.com",
96168
},
97169
}
98170
for _, tc := range testCases {
99171
opt := &ExternalCAOption{}
100-
assert.NilError(t, opt.Set(tc.externalCA))
101-
assert.Check(t, is.Equal(tc.expected, opt.String()))
172+
for _, extCA := range tc.externalCAs {
173+
assert.NilError(t, opt.Set(extCA))
174+
}
175+
assert.Check(t, is.DeepEqual(tc.expected, opt.Value()))
176+
assert.Check(t, is.Equal(tc.expectedString, opt.String()))
102177
}
103178
}
104179

0 commit comments

Comments
 (0)