Compare commits
57 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 370c28948e | |||
| dc017bdda3 | |||
| feb6f439e3 | |||
| 8bc4062fc0 | |||
| 84cc7d87cc | |||
| c1c3d3b3aa | |||
| 048a846146 | |||
| 33dacda24f | |||
| fcc05e5ea1 | |||
| 58061d25f6 | |||
| 55b2abb0ca | |||
| 4c3b87d922 | |||
| e77605c83d | |||
| 0196098721 | |||
| 6ebf765040 | |||
| f508ce9db7 | |||
| 897293c7c7 | |||
| 2c04354315 | |||
| 9c8a91d22b | |||
| ff945151ef | |||
| 4571d90f20 | |||
| 55c4c88966 | |||
| f33a69f6ee | |||
| d3cb89ee53 | |||
| 433014bcfb | |||
| 61cb016851 | |||
| 53c4602909 | |||
| 830d6595e7 | |||
| 13048444cc | |||
| 3e293e6bd1 | |||
| 41b3ea7e47 | |||
| d6eeeb6259 | |||
| 3e157d5293 | |||
| 1fdf84b8e9 | |||
| 376b99c6d6 | |||
| 0de4e6e9a7 | |||
| 3c87f01b18 | |||
| de40c2b172 | |||
| d513e46bfc | |||
| 2b74b90efb | |||
| 05343b36a2 | |||
| f90db254d7 | |||
| 0dcfdde336 | |||
| 03cd1dc50a | |||
| 42811a7eb9 | |||
| be966aa194 | |||
| b22fe0fb14 | |||
| 4eb050071e | |||
| 08c4fdfa7a | |||
| 6aa1b37c8d | |||
| e82920d76d | |||
| 82123939f7 | |||
| 48d30b5b32 | |||
| 5941f4104a | |||
| 18f33b337d | |||
| 9ecc69d17e | |||
| 6f49197cab |
@ -42,6 +42,7 @@ jobs:
|
||||
docker: [{image: 'docker:19.03-git'}]
|
||||
environment:
|
||||
DOCKER_BUILDKIT: 1
|
||||
BUILDX_VERSION: "v0.5.1"
|
||||
parallelism: 3
|
||||
steps:
|
||||
- checkout
|
||||
@ -55,21 +56,14 @@ jobs:
|
||||
- run:
|
||||
name: "Docker info"
|
||||
command: docker info
|
||||
- run:
|
||||
name: "Cross - build image"
|
||||
command: |
|
||||
docker build --progress=plain -f dockerfiles/Dockerfile.cross --tag cli-builder:$CIRCLE_BUILD_NUM .
|
||||
- run:
|
||||
name: "Cross"
|
||||
command: |
|
||||
name=cross-$CIRCLE_BUILD_NUM-$CIRCLE_NODE_INDEX
|
||||
docker run \
|
||||
-e CROSS_GROUP=$CIRCLE_NODE_INDEX \
|
||||
--name $name cli-builder:$CIRCLE_BUILD_NUM \
|
||||
make cross
|
||||
docker cp \
|
||||
$name:/go/src/github.com/docker/cli/build \
|
||||
/work/build
|
||||
- run: apk add make curl
|
||||
- run: mkdir -vp ~/.docker/cli-plugins/
|
||||
- run: curl -fsSL --output ~/.docker/cli-plugins/docker-buildx https://github.com/docker/buildx/releases/download/${BUILDX_VERSION}/buildx-${BUILDX_VERSION}.linux-amd64
|
||||
- run: chmod a+x ~/.docker/cli-plugins/docker-buildx
|
||||
- run: docker buildx version
|
||||
- run: docker context create buildctx
|
||||
- run: docker buildx create --use buildctx && docker buildx inspect --bootstrap
|
||||
- run: GROUP_INDEX=$CIRCLE_NODE_INDEX GROUP_TOTAL=$CIRCLE_NODE_TOTAL docker buildx bake cross --progress=plain
|
||||
- store_artifacts:
|
||||
path: /work/build
|
||||
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
.circleci
|
||||
.dockerignore
|
||||
.git
|
||||
.github
|
||||
.gitignore
|
||||
appveyor.yml
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@ -8,8 +8,7 @@
|
||||
Thumbs.db
|
||||
.editorconfig
|
||||
/build/
|
||||
cli/winresources/rsrc_386.syso
|
||||
cli/winresources/rsrc_amd64.syso
|
||||
cli/winresources/rsrc_*.syso
|
||||
/man/man1/
|
||||
/man/man5/
|
||||
/man/man8/
|
||||
|
||||
61
Dockerfile
Normal file
61
Dockerfile
Normal file
@ -0,0 +1,61 @@
|
||||
#syntax=docker/dockerfile:1.2
|
||||
|
||||
ARG BASE_VARIANT=alpine
|
||||
ARG GO_VERSION=1.13.15
|
||||
|
||||
FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-${BASE_VARIANT} AS gostable
|
||||
FROM --platform=$BUILDPLATFORM golang:1.16-${BASE_VARIANT} AS golatest
|
||||
|
||||
FROM gostable AS go-linux
|
||||
FROM golatest AS go-darwin
|
||||
FROM golatest AS go-windows-amd64
|
||||
FROM golatest AS go-windows-386
|
||||
FROM golatest AS go-windows-arm
|
||||
FROM --platform=$BUILDPLATFORM tonistiigi/golang:497feff1-${BASE_VARIANT} AS go-windows-arm64
|
||||
FROM go-windows-${TARGETARCH} AS go-windows
|
||||
|
||||
FROM --platform=$BUILDPLATFORM tonistiigi/xx@sha256:620d36a9d7f1e3b102a5c7e8eff12081ac363828b3a44390f24fa8da2d49383d AS xx
|
||||
|
||||
FROM go-${TARGETOS} AS build-base-alpine
|
||||
COPY --from=xx / /
|
||||
RUN apk add --no-cache clang lld llvm file git
|
||||
WORKDIR /go/src/github.com/docker/cli
|
||||
|
||||
FROM build-base-alpine AS build-alpine
|
||||
ARG TARGETPLATFORM
|
||||
# gcc is installed for libgcc only
|
||||
RUN xx-apk add --no-cache musl-dev gcc
|
||||
|
||||
FROM go-${TARGETOS} AS build-base-buster
|
||||
COPY --from=xx / /
|
||||
RUN apt-get update && apt-get install --no-install-recommends -y clang lld file
|
||||
WORKDIR /go/src/github.com/docker/cli
|
||||
|
||||
FROM build-base-buster AS build-buster
|
||||
ARG TARGETPLATFORM
|
||||
RUN xx-apt install --no-install-recommends -y libc6-dev libgcc-8-dev
|
||||
|
||||
FROM build-${BASE_VARIANT} AS build
|
||||
# GO_LINKMODE defines if static or dynamic binary should be produced
|
||||
ARG GO_LINKMODE=static
|
||||
# GO_BUILDTAGS defines additional build tags
|
||||
ARG GO_BUILDTAGS
|
||||
# GO_STRIP strips debugging symbols if set
|
||||
ARG GO_STRIP
|
||||
# CGO_ENABLED manually sets if cgo is used
|
||||
ARG CGO_ENABLED
|
||||
# VERSION sets the version for the produced binary
|
||||
ARG VERSION
|
||||
RUN --mount=ro --mount=type=cache,target=/root/.cache \
|
||||
--mount=from=dockercore/golang-cross:xx-sdk-extras,target=/xx-sdk,src=/xx-sdk \
|
||||
--mount=type=tmpfs,target=cli/winresources \
|
||||
xx-go --wrap && \
|
||||
# export GOCACHE=$(go env GOCACHE)/$(xx-info)$([ -f /etc/alpine-release ] && echo "alpine") && \
|
||||
TARGET=/out ./scripts/build/binary && \
|
||||
xx-verify $([ "$GO_LINKMODE" = "static" ] && echo "--static") /out/docker
|
||||
|
||||
FROM build-base-${BASE_VARIANT} AS dev
|
||||
COPY . .
|
||||
|
||||
FROM scratch AS binary
|
||||
COPY --from=build /out .
|
||||
17
Makefile
17
Makefile
@ -30,8 +30,7 @@ lint: ## run all the lint tools
|
||||
gometalinter --config gometalinter.json ./...
|
||||
|
||||
.PHONY: binary
|
||||
binary: ## build executable for Linux
|
||||
@echo "WARNING: binary creates a Linux executable. Use cross for macOS or Windows."
|
||||
binary:
|
||||
./scripts/build/binary
|
||||
|
||||
.PHONY: plugins
|
||||
@ -39,28 +38,20 @@ plugins: ## build example CLI plugins
|
||||
./scripts/build/plugins
|
||||
|
||||
.PHONY: cross
|
||||
cross: ## build executable for macOS and Windows
|
||||
./scripts/build/cross
|
||||
|
||||
.PHONY: binary-windows
|
||||
binary-windows: ## build executable for Windows
|
||||
./scripts/build/windows
|
||||
cross:
|
||||
./scripts/build/binary
|
||||
|
||||
.PHONY: plugins-windows
|
||||
plugins-windows: ## build example CLI plugins for Windows
|
||||
./scripts/build/plugins-windows
|
||||
|
||||
.PHONY: binary-osx
|
||||
binary-osx: ## build executable for macOS
|
||||
./scripts/build/osx
|
||||
|
||||
.PHONY: plugins-osx
|
||||
plugins-osx: ## build example CLI plugins for macOS
|
||||
./scripts/build/plugins-osx
|
||||
|
||||
.PHONY: dynbinary
|
||||
dynbinary: ## build dynamically linked binary
|
||||
./scripts/build/dynbinary
|
||||
GO_LINKMODE=dynamic ./scripts/build/binary
|
||||
|
||||
vendor: vendor.conf ## check that vendor matches vendor.conf
|
||||
rm -rf vendor
|
||||
|
||||
25
README.md
25
README.md
@ -12,18 +12,31 @@ Development
|
||||
|
||||
`docker/cli` is developed using Docker.
|
||||
|
||||
Build a linux binary:
|
||||
Build CLI from source:
|
||||
|
||||
```
|
||||
$ make -f docker.Makefile binary
|
||||
$ docker buildx bake
|
||||
```
|
||||
|
||||
Build binaries for all supported platforms:
|
||||
|
||||
```
|
||||
$ make -f docker.Makefile cross
|
||||
$ docker buildx bake cross
|
||||
```
|
||||
|
||||
Build for a specific platform:
|
||||
|
||||
```
|
||||
$ docker buildx bake --set binary.platform=linux/arm64
|
||||
```
|
||||
|
||||
Build dynamic binary for glibc or musl:
|
||||
|
||||
```
|
||||
$ USE_GLIBC=1 docker buildx bake dynbinary
|
||||
```
|
||||
|
||||
|
||||
Run all linting:
|
||||
|
||||
```
|
||||
@ -44,12 +57,6 @@ Start an interactive development environment:
|
||||
$ make -f docker.Makefile shell
|
||||
```
|
||||
|
||||
In the development environment you can run many tasks, including build binaries:
|
||||
|
||||
```
|
||||
$ make binary
|
||||
```
|
||||
|
||||
Legal
|
||||
=====
|
||||
*Brought to you courtesy of our legal counsel. For more context,
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
package manager
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
exec "golang.org/x/sys/execabs"
|
||||
)
|
||||
|
||||
// Candidate represents a possible plugin candidate, for mocking purposes
|
||||
|
||||
@ -3,7 +3,6 @@ package manager
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
@ -12,6 +11,7 @@ import (
|
||||
"github.com/docker/cli/cli/config"
|
||||
"github.com/fvbommel/sortorder"
|
||||
"github.com/spf13/cobra"
|
||||
exec "golang.org/x/sys/execabs"
|
||||
)
|
||||
|
||||
// ReexecEnvvar is the name of an ennvar which is set to the command
|
||||
|
||||
@ -1,10 +1,6 @@
|
||||
package context
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
|
||||
"github.com/docker/cli/cli"
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/spf13/cobra"
|
||||
@ -30,20 +26,3 @@ func NewContextCommand(dockerCli command.Cli) *cobra.Command {
|
||||
)
|
||||
return cmd
|
||||
}
|
||||
|
||||
const restrictedNamePattern = "^[a-zA-Z0-9][a-zA-Z0-9_.+-]+$"
|
||||
|
||||
var restrictedNameRegEx = regexp.MustCompile(restrictedNamePattern)
|
||||
|
||||
func validateContextName(name string) error {
|
||||
if name == "" {
|
||||
return errors.New("context name cannot be empty")
|
||||
}
|
||||
if name == "default" {
|
||||
return errors.New(`"default" is a reserved context name`)
|
||||
}
|
||||
if !restrictedNameRegEx.MatchString(name) {
|
||||
return fmt.Errorf("context name %q is invalid, names are validated against regexp %q", name, restrictedNamePattern)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -137,7 +137,7 @@ func createNewContext(o *CreateOptions, stackOrchestrator command.Orchestrator,
|
||||
}
|
||||
|
||||
func checkContextNameForCreation(s store.Reader, name string) error {
|
||||
if err := validateContextName(name); err != nil {
|
||||
if err := store.ValidateContextName(name); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := s.GetMetadata(name); !store.IsErrContextDoesNotExist(err) {
|
||||
|
||||
@ -77,7 +77,7 @@ func writeTo(dockerCli command.Cli, reader io.Reader, dest string) error {
|
||||
|
||||
// RunExport exports a Docker context
|
||||
func RunExport(dockerCli command.Cli, opts *ExportOptions) error {
|
||||
if err := validateContextName(opts.ContextName); err != nil && opts.ContextName != command.DefaultContextName {
|
||||
if err := store.ValidateContextName(opts.ContextName); err != nil && opts.ContextName != command.DefaultContextName {
|
||||
return err
|
||||
}
|
||||
ctxMeta, err := dockerCli.ContextStore().GetMetadata(opts.ContextName)
|
||||
|
||||
@ -68,7 +68,7 @@ func newUpdateCommand(dockerCli command.Cli) *cobra.Command {
|
||||
|
||||
// RunUpdate updates a Docker context
|
||||
func RunUpdate(cli command.Cli, o *UpdateOptions) error {
|
||||
if err := validateContextName(o.Name); err != nil {
|
||||
if err := store.ValidateContextName(o.Name); err != nil {
|
||||
return err
|
||||
}
|
||||
s := cli.ContextStore()
|
||||
|
||||
@ -5,6 +5,7 @@ import (
|
||||
"os"
|
||||
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/cli/cli/context/store"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@ -23,7 +24,7 @@ func newUseCommand(dockerCli command.Cli) *cobra.Command {
|
||||
|
||||
// RunUse set the current Docker context
|
||||
func RunUse(dockerCli command.Cli, name string) error {
|
||||
if err := validateContextName(name); err != nil && name != "default" {
|
||||
if err := store.ValidateContextName(name); err != nil && name != "default" {
|
||||
return err
|
||||
}
|
||||
if _, err := dockerCli.ContextStore().GetMetadata(name); err != nil && name != "default" {
|
||||
|
||||
@ -9,7 +9,6 @@ import (
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
@ -24,6 +23,7 @@ import (
|
||||
"github.com/docker/docker/pkg/streamformatter"
|
||||
"github.com/docker/docker/pkg/stringid"
|
||||
"github.com/pkg/errors"
|
||||
exec "golang.org/x/sys/execabs"
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
@ -78,7 +78,7 @@ func runBuildBuildKit(dockerCli command.Cli, options buildOptions) error {
|
||||
if options.dockerfileFromStdin() {
|
||||
return errStdinConflict
|
||||
}
|
||||
rc, isArchive, err := build.DetectArchiveReader(os.Stdin)
|
||||
rc, isArchive, err := build.DetectArchiveReader(dockerCli.In())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -98,7 +98,7 @@ func runBuildBuildKit(dockerCli command.Cli, options buildOptions) error {
|
||||
case isLocalDir(options.context):
|
||||
contextDir = options.context
|
||||
if options.dockerfileFromStdin() {
|
||||
dockerfileReader = os.Stdin
|
||||
dockerfileReader = dockerCli.In()
|
||||
} else if options.dockerfileName != "" {
|
||||
dockerfileName = filepath.Base(options.dockerfileName)
|
||||
dockerfileDir = filepath.Dir(options.dockerfileName)
|
||||
|
||||
@ -63,6 +63,9 @@ func RegistryAuthenticationPrivilegedFunc(cli Cli, index *registrytypes.IndexInf
|
||||
indexServer := registry.GetAuthConfigKey(index)
|
||||
isDefaultRegistry := indexServer == ElectAuthServer(context.Background(), cli)
|
||||
authConfig, err := GetDefaultAuthConfig(cli, true, indexServer, isDefaultRegistry)
|
||||
if authConfig == nil {
|
||||
authConfig = &types.AuthConfig{}
|
||||
}
|
||||
if err != nil {
|
||||
fmt.Fprintf(cli.Err(), "Unable to retrieve stored credentials for %s, error: %s.\n", indexServer, err)
|
||||
}
|
||||
|
||||
@ -111,11 +111,12 @@ func runLogin(dockerCli command.Cli, opts loginOptions) error { //nolint: gocycl
|
||||
serverAddress = authServer
|
||||
}
|
||||
|
||||
var err error
|
||||
var authConfig *types.AuthConfig
|
||||
var response registrytypes.AuthenticateOKBody
|
||||
isDefaultRegistry := serverAddress == authServer
|
||||
authConfig, err = command.GetDefaultAuthConfig(dockerCli, opts.user == "" && opts.password == "", serverAddress, isDefaultRegistry)
|
||||
authConfig, err := command.GetDefaultAuthConfig(dockerCli, opts.user == "" && opts.password == "", serverAddress, isDefaultRegistry)
|
||||
if authConfig == nil {
|
||||
authConfig = &types.AuthConfig{}
|
||||
}
|
||||
if err == nil && authConfig.Username != "" && authConfig.Password != "" {
|
||||
response, err = loginWithCredStoreCreds(ctx, dockerCli, authConfig)
|
||||
}
|
||||
|
||||
@ -165,7 +165,7 @@ func updateConfigFromDefaults(defaultUpdateConfig *api.UpdateConfig) *swarm.Upda
|
||||
}
|
||||
|
||||
func (opts updateOptions) updateConfig(flags *pflag.FlagSet) *swarm.UpdateConfig {
|
||||
if !anyChanged(flags, flagUpdateParallelism, flagUpdateDelay, flagUpdateMonitor, flagUpdateFailureAction, flagUpdateMaxFailureRatio) {
|
||||
if !anyChanged(flags, flagUpdateParallelism, flagUpdateDelay, flagUpdateMonitor, flagUpdateFailureAction, flagUpdateMaxFailureRatio, flagUpdateOrder) {
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -194,7 +194,7 @@ func (opts updateOptions) updateConfig(flags *pflag.FlagSet) *swarm.UpdateConfig
|
||||
}
|
||||
|
||||
func (opts updateOptions) rollbackConfig(flags *pflag.FlagSet) *swarm.UpdateConfig {
|
||||
if !anyChanged(flags, flagRollbackParallelism, flagRollbackDelay, flagRollbackMonitor, flagRollbackFailureAction, flagRollbackMaxFailureRatio) {
|
||||
if !anyChanged(flags, flagRollbackParallelism, flagRollbackDelay, flagRollbackMonitor, flagRollbackFailureAction, flagRollbackMaxFailureRatio, flagRollbackOrder) {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@ -289,6 +289,22 @@ func TestToServiceUpdateRollback(t *testing.T) {
|
||||
assert.Check(t, is.DeepEqual(service.RollbackConfig, expected.RollbackConfig))
|
||||
}
|
||||
|
||||
func TestToServiceUpdateRollbackOrder(t *testing.T) {
|
||||
flags := newCreateCommand(nil).Flags()
|
||||
flags.Set("update-order", "start-first")
|
||||
flags.Set("rollback-order", "start-first")
|
||||
|
||||
o := newServiceOptions()
|
||||
o.mode = "replicated"
|
||||
o.update = updateOptions{order: "start-first"}
|
||||
o.rollback = updateOptions{order: "start-first"}
|
||||
|
||||
service, err := o.ToService(context.Background(), &fakeClient{}, flags)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(service.UpdateConfig.Order, o.update.order))
|
||||
assert.Check(t, is.Equal(service.RollbackConfig.Order, o.rollback.order))
|
||||
}
|
||||
|
||||
func TestToServiceMaxReplicasGlobalModeConflict(t *testing.T) {
|
||||
opt := serviceOptions{
|
||||
mode: "global",
|
||||
|
||||
@ -99,6 +99,7 @@ func ServiceProgress(ctx context.Context, client client.APIClient, serviceID str
|
||||
convergedAt time.Time
|
||||
monitor = 5 * time.Second
|
||||
rollback bool
|
||||
message *progress.Progress
|
||||
)
|
||||
|
||||
for {
|
||||
@ -140,8 +141,9 @@ func ServiceProgress(ctx context.Context, client client.APIClient, serviceID str
|
||||
return fmt.Errorf("service rollback paused: %s", service.UpdateStatus.Message)
|
||||
case swarm.UpdateStateRollbackCompleted:
|
||||
if !converged {
|
||||
return fmt.Errorf("service rolled back: %s", service.UpdateStatus.Message)
|
||||
message = &progress.Progress{ID: "rollback", Message: service.UpdateStatus.Message}
|
||||
}
|
||||
rollback = true
|
||||
}
|
||||
}
|
||||
if converged && time.Since(convergedAt) >= monitor {
|
||||
@ -149,7 +151,9 @@ func ServiceProgress(ctx context.Context, client client.APIClient, serviceID str
|
||||
ID: "verify",
|
||||
Action: "Service converged",
|
||||
})
|
||||
|
||||
if message != nil {
|
||||
progressOut.WriteProgress(*message)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@ -24,17 +24,38 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
initConfigDir sync.Once
|
||||
initConfigDir = new(sync.Once)
|
||||
configDir string
|
||||
homeDir string
|
||||
)
|
||||
|
||||
// resetHomeDir is used in testing to reset the "homeDir" package variable to
|
||||
// force re-lookup of the home directory between tests.
|
||||
func resetHomeDir() {
|
||||
homeDir = ""
|
||||
}
|
||||
|
||||
func getHomeDir() string {
|
||||
if homeDir == "" {
|
||||
homeDir = homedir.Get()
|
||||
}
|
||||
return homeDir
|
||||
}
|
||||
|
||||
// resetConfigDir is used in testing to reset the "configDir" package variable
|
||||
// and its sync.Once to force re-lookup between tests.
|
||||
func resetConfigDir() {
|
||||
configDir = ""
|
||||
initConfigDir = new(sync.Once)
|
||||
}
|
||||
|
||||
func setConfigDir() {
|
||||
if configDir != "" {
|
||||
return
|
||||
}
|
||||
configDir = os.Getenv("DOCKER_CONFIG")
|
||||
if configDir == "" {
|
||||
configDir = filepath.Join(homedir.Get(), configFileDir)
|
||||
configDir = filepath.Join(getHomeDir(), configFileDir)
|
||||
}
|
||||
}
|
||||
|
||||
@ -83,10 +104,15 @@ func LoadFromReader(configData io.Reader) (*configfile.ConfigFile, error) {
|
||||
return &configFile, err
|
||||
}
|
||||
|
||||
// TODO remove this temporary hack, which is used to warn about the deprecated ~/.dockercfg file
|
||||
var printLegacyFileWarning bool
|
||||
|
||||
// Load reads the configuration files in the given directory, and sets up
|
||||
// the auth config information and returns values.
|
||||
// FIXME: use the internal golang config parser
|
||||
func Load(configDir string) (*configfile.ConfigFile, error) {
|
||||
printLegacyFileWarning = false
|
||||
|
||||
if configDir == "" {
|
||||
configDir = Dir()
|
||||
}
|
||||
@ -109,12 +135,9 @@ func Load(configDir string) (*configfile.ConfigFile, error) {
|
||||
}
|
||||
|
||||
// Can't find latest config file so check for the old one
|
||||
home, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
return configFile, errors.Wrap(err, oldConfigfile)
|
||||
}
|
||||
filename = filepath.Join(home, oldConfigfile)
|
||||
filename = filepath.Join(getHomeDir(), oldConfigfile)
|
||||
if file, err := os.Open(filename); err == nil {
|
||||
printLegacyFileWarning = true
|
||||
defer file.Close()
|
||||
if err := configFile.LegacyLoadFromReader(file); err != nil {
|
||||
return configFile, errors.Wrap(err, filename)
|
||||
@ -130,6 +153,9 @@ func LoadDefaultConfigFile(stderr io.Writer) *configfile.ConfigFile {
|
||||
if err != nil {
|
||||
fmt.Fprintf(stderr, "WARNING: Error loading config file: %v\n", err)
|
||||
}
|
||||
if printLegacyFileWarning {
|
||||
_, _ = fmt.Fprintln(stderr, "WARNING: Support for the legacy ~/.dockercfg configuration file and file-format is deprecated and will be removed in an upcoming release")
|
||||
}
|
||||
if !configFile.ContainsAuth() {
|
||||
configFile.CredentialsStore = credentials.DetectDefaultStore(configFile.CredentialsStore)
|
||||
}
|
||||
|
||||
@ -12,9 +12,11 @@ import (
|
||||
|
||||
"github.com/docker/cli/cli/config/configfile"
|
||||
"github.com/docker/cli/cli/config/credentials"
|
||||
"github.com/docker/cli/cli/config/types"
|
||||
"gotest.tools/v3/assert"
|
||||
is "gotest.tools/v3/assert/cmp"
|
||||
"gotest.tools/v3/env"
|
||||
"gotest.tools/v3/fs"
|
||||
)
|
||||
|
||||
var homeKey = "HOME"
|
||||
@ -115,6 +117,7 @@ password`: "Invalid Auth config file",
|
||||
email`: "Invalid auth configuration file",
|
||||
}
|
||||
|
||||
resetHomeDir()
|
||||
tmpHome, err := ioutil.TempDir("", "config-test")
|
||||
assert.NilError(t, err)
|
||||
defer os.RemoveAll(tmpHome)
|
||||
@ -131,6 +134,7 @@ email`: "Invalid auth configuration file",
|
||||
}
|
||||
|
||||
func TestOldValidAuth(t *testing.T) {
|
||||
resetHomeDir()
|
||||
tmpHome, err := ioutil.TempDir("", "config-test")
|
||||
assert.NilError(t, err)
|
||||
defer os.RemoveAll(tmpHome)
|
||||
@ -165,6 +169,7 @@ func TestOldValidAuth(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestOldJSONInvalid(t *testing.T) {
|
||||
resetHomeDir()
|
||||
tmpHome, err := ioutil.TempDir("", "config-test")
|
||||
assert.NilError(t, err)
|
||||
defer os.RemoveAll(tmpHome)
|
||||
@ -184,6 +189,7 @@ func TestOldJSONInvalid(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestOldJSON(t *testing.T) {
|
||||
resetHomeDir()
|
||||
tmpHome, err := ioutil.TempDir("", "config-test")
|
||||
assert.NilError(t, err)
|
||||
defer os.RemoveAll(tmpHome)
|
||||
@ -219,6 +225,31 @@ func TestOldJSON(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestOldJSONFallbackDeprecationWarning(t *testing.T) {
|
||||
js := `{"https://index.docker.io/v1/":{"auth":"am9lam9lOmhlbGxv","email":"user@example.com"}}`
|
||||
tmpHome := fs.NewDir(t, t.Name(), fs.WithFile(oldConfigfile, js))
|
||||
defer tmpHome.Remove()
|
||||
defer env.PatchAll(t, map[string]string{homeKey: tmpHome.Path(), "DOCKER_CONFIG": ""})()
|
||||
|
||||
// reset the homeDir, configDir, and its sync.Once, to force them being resolved again
|
||||
resetHomeDir()
|
||||
resetConfigDir()
|
||||
|
||||
buffer := new(bytes.Buffer)
|
||||
configFile := LoadDefaultConfigFile(buffer)
|
||||
expected := configfile.New(tmpHome.Join(configFileDir, ConfigFileName))
|
||||
expected.AuthConfigs = map[string]types.AuthConfig{
|
||||
"https://index.docker.io/v1/": {
|
||||
Username: "joejoe",
|
||||
Password: "hello",
|
||||
Email: "user@example.com",
|
||||
ServerAddress: "https://index.docker.io/v1/",
|
||||
},
|
||||
}
|
||||
assert.Assert(t, strings.Contains(buffer.String(), "WARNING: Support for the legacy ~/.dockercfg configuration file and file-format is deprecated and will be removed in an upcoming release"))
|
||||
assert.Check(t, is.DeepEqual(expected, configFile))
|
||||
}
|
||||
|
||||
func TestNewJSON(t *testing.T) {
|
||||
tmpHome, err := ioutil.TempDir("", "config-test")
|
||||
assert.NilError(t, err)
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
package credentials
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
exec "golang.org/x/sys/execabs"
|
||||
)
|
||||
|
||||
// DetectDefaultStore return the default credentials store for the platform if
|
||||
|
||||
@ -20,7 +20,6 @@ import (
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
@ -29,6 +28,7 @@ import (
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
exec "golang.org/x/sys/execabs"
|
||||
)
|
||||
|
||||
// New returns net.Conn
|
||||
|
||||
@ -7,19 +7,24 @@ import (
|
||||
"bytes"
|
||||
_ "crypto/sha256" // ensure ids can be computed
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/docker/errdefs"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
const restrictedNamePattern = "^[a-zA-Z0-9][a-zA-Z0-9_.+-]+$"
|
||||
|
||||
var restrictedNameRegEx = regexp.MustCompile(restrictedNamePattern)
|
||||
|
||||
// Store provides a context store for easily remembering endpoints configuration
|
||||
type Store interface {
|
||||
Reader
|
||||
@ -184,6 +189,20 @@ func (s *store) GetStorageInfo(contextName string) StorageInfo {
|
||||
}
|
||||
}
|
||||
|
||||
// ValidateContextName checks a context name is valid.
|
||||
func ValidateContextName(name string) error {
|
||||
if name == "" {
|
||||
return errors.New("context name cannot be empty")
|
||||
}
|
||||
if name == "default" {
|
||||
return errors.New(`"default" is a reserved context name`)
|
||||
}
|
||||
if !restrictedNameRegEx.MatchString(name) {
|
||||
return fmt.Errorf("context name %q is invalid, names are validated against regexp %q", name, restrictedNamePattern)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Export exports an existing namespace into an opaque data stream
|
||||
// This stream is actually a tarball containing context metadata and TLS materials, but it does
|
||||
// not map 1:1 the layout of the context store (don't try to restore it manually without calling store.Import)
|
||||
@ -295,6 +314,19 @@ func Import(name string, s Writer, reader io.Reader) error {
|
||||
}
|
||||
}
|
||||
|
||||
func isValidFilePath(p string) error {
|
||||
if p != metaFile && !strings.HasPrefix(p, "tls/") {
|
||||
return errors.New("unexpected context file")
|
||||
}
|
||||
if path.Clean(p) != p {
|
||||
return errors.New("unexpected path format")
|
||||
}
|
||||
if strings.Contains(p, `\`) {
|
||||
return errors.New(`unexpected '\' in path`)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func importTar(name string, s Writer, reader io.Reader) error {
|
||||
tr := tar.NewReader(&LimitedReader{R: reader, N: maxAllowedFileSizeToImport})
|
||||
tlsData := ContextTLSData{
|
||||
@ -309,10 +341,13 @@ func importTar(name string, s Writer, reader io.Reader) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if hdr.Typeflag == tar.TypeDir {
|
||||
if hdr.Typeflag != tar.TypeReg {
|
||||
// skip this entry, only taking files into account
|
||||
continue
|
||||
}
|
||||
if err := isValidFilePath(hdr.Name); err != nil {
|
||||
return errors.Wrap(err, hdr.Name)
|
||||
}
|
||||
if hdr.Name == metaFile {
|
||||
data, err := ioutil.ReadAll(tr)
|
||||
if err != nil {
|
||||
@ -358,10 +393,13 @@ func importZip(name string, s Writer, reader io.Reader) error {
|
||||
var importedMetaFile bool
|
||||
for _, zf := range zr.File {
|
||||
fi := zf.FileInfo()
|
||||
if fi.IsDir() {
|
||||
// skip this entry, only taking files into account
|
||||
if !fi.Mode().IsRegular() {
|
||||
// skip this entry, only taking regular files into account
|
||||
continue
|
||||
}
|
||||
if err := isValidFilePath(zf.Name); err != nil {
|
||||
return errors.Wrap(err, zf.Name)
|
||||
}
|
||||
if zf.Name == metaFile {
|
||||
f, err := zf.Open()
|
||||
if err != nil {
|
||||
@ -408,6 +446,9 @@ func parseMetadata(data []byte, name string) (Metadata, error) {
|
||||
if err := json.Unmarshal(data, &meta); err != nil {
|
||||
return meta, err
|
||||
}
|
||||
if err := ValidateContextName(name); err != nil {
|
||||
return Metadata{}, err
|
||||
}
|
||||
meta.Name = name
|
||||
return meta, nil
|
||||
}
|
||||
|
||||
@ -175,7 +175,7 @@ func TestImportTarInvalid(t *testing.T) {
|
||||
var r io.Reader = source
|
||||
s := New(testDir, testCfg)
|
||||
err = Import("tarInvalid", s, r)
|
||||
assert.ErrorContains(t, err, "invalid context: no metadata found")
|
||||
assert.ErrorContains(t, err, "unexpected context file")
|
||||
}
|
||||
|
||||
func TestImportZip(t *testing.T) {
|
||||
@ -254,5 +254,5 @@ func TestImportZipInvalid(t *testing.T) {
|
||||
var r io.Reader = source
|
||||
s := New(testDir, testCfg)
|
||||
err = Import("zipInvalid", s, r)
|
||||
assert.ErrorContains(t, err, "invalid context: no metadata found")
|
||||
assert.ErrorContains(t, err, "unexpected context file")
|
||||
}
|
||||
|
||||
@ -29,3 +29,32 @@ func TestConfigModification(t *testing.T) {
|
||||
assert.Equal(t, &testEP2{}, cfgCopy.endpointTypes["ep1"]())
|
||||
assert.Equal(t, &testEP3{}, cfgCopy.endpointTypes["ep2"]())
|
||||
}
|
||||
|
||||
func TestValidFilePaths(t *testing.T) {
|
||||
paths := map[string]bool{
|
||||
"tls/_/../../something": false,
|
||||
"tls/../../something": false,
|
||||
"../../something": false,
|
||||
"/tls/absolute/unix/path": false,
|
||||
`C:\tls\absolute\windows\path`: false,
|
||||
"C:/tls/absolute/windows/path": false,
|
||||
"tls/kubernetes/key.pem": true,
|
||||
}
|
||||
for p, expectedValid := range paths {
|
||||
err := isValidFilePath(p)
|
||||
assert.Equal(t, err == nil, expectedValid, "%q should report valid as: %v", p, expectedValid)
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateContextName(t *testing.T) {
|
||||
names := map[string]bool{
|
||||
"../../invalid/escape": false,
|
||||
"/invalid/absolute": false,
|
||||
`\invalid\windows`: false,
|
||||
"validname": true,
|
||||
}
|
||||
for n, expectedValid := range names {
|
||||
err := ValidateContextName(n)
|
||||
assert.Equal(t, err == nil, expectedValid, "%q should report valid as: %v", n, expectedValid)
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@ These resources are used to provide
|
||||
* An icon
|
||||
* A Windows manifest declaring Windows version support
|
||||
|
||||
The resource object files are generated with go generate.
|
||||
The resource object files are generated when building with scripts/build/binary .
|
||||
The resource source files are located in scripts/winresources.
|
||||
This occurs automatically when you run scripts/build/windows.
|
||||
|
||||
@ -14,5 +14,3 @@ is included.
|
||||
|
||||
*/
|
||||
package winresources
|
||||
|
||||
//go:generate ../../scripts/gen/windows-resources
|
||||
|
||||
@ -17,7 +17,9 @@ import (
|
||||
func TestClientDebugEnabled(t *testing.T) {
|
||||
defer debug.Disable()
|
||||
|
||||
tcmd := newDockerCommand(&command.DockerCli{})
|
||||
cli, err := command.NewDockerCli()
|
||||
assert.NilError(t, err)
|
||||
tcmd := newDockerCommand(cli)
|
||||
tcmd.SetFlag("debug", "true")
|
||||
cmd, _, err := tcmd.HandleGlobalFlags()
|
||||
assert.NilError(t, err)
|
||||
|
||||
@ -935,7 +935,7 @@ __docker_complete_log_options() {
|
||||
# awslogs does not implement the $common_options2.
|
||||
local awslogs_options="$common_options1 awslogs-create-group awslogs-credentials-endpoint awslogs-datetime-format awslogs-group awslogs-multiline-pattern awslogs-region awslogs-stream tag"
|
||||
|
||||
local fluentd_options="$common_options1 $common_options2 fluentd-address fluentd-async-connect fluentd-buffer-limit fluentd-retry-wait fluentd-max-retries fluentd-sub-second-precision tag"
|
||||
local fluentd_options="$common_options1 $common_options2 fluentd-address fluentd-async fluentd-buffer-limit fluentd-request-ack fluentd-retry-wait fluentd-max-retries fluentd-sub-second-precision tag"
|
||||
local gcplogs_options="$common_options1 $common_options2 gcp-log-cmd gcp-meta-id gcp-meta-name gcp-meta-zone gcp-project"
|
||||
local gelf_options="$common_options1 $common_options2 gelf-address gelf-compression-level gelf-compression-type gelf-tcp-max-reconnect gelf-tcp-reconnect-delay tag"
|
||||
local journald_options="$common_options1 $common_options2 tag"
|
||||
@ -1955,6 +1955,7 @@ _docker_container_run_and_create() {
|
||||
--pid
|
||||
--pids-limit
|
||||
--publish -p
|
||||
--pull
|
||||
--restart
|
||||
--runtime
|
||||
--security-opt
|
||||
@ -2153,6 +2154,10 @@ _docker_container_run_and_create() {
|
||||
esac
|
||||
return
|
||||
;;
|
||||
--pull)
|
||||
COMPREPLY=( $( compgen -W 'always missing never' -- "$cur" ) )
|
||||
return
|
||||
;;
|
||||
--runtime)
|
||||
__docker_complete_runtimes
|
||||
return
|
||||
@ -2548,6 +2553,7 @@ _docker_daemon() {
|
||||
--ip-forward=false
|
||||
--ip-masq=false
|
||||
--iptables=false
|
||||
--ip6tables
|
||||
--ipv6
|
||||
--live-restore
|
||||
--no-new-privileges
|
||||
@ -3601,7 +3607,7 @@ _docker_service_ls() {
|
||||
return
|
||||
;;
|
||||
mode)
|
||||
COMPREPLY=( $( compgen -W "global replicated" -- "${cur##*=}" ) )
|
||||
COMPREPLY=( $( compgen -W "global global-job replicated replicated-job" -- "${cur##*=}" ) )
|
||||
return
|
||||
;;
|
||||
name)
|
||||
@ -3731,6 +3737,7 @@ _docker_service_update_and_create() {
|
||||
--limit-pids
|
||||
--log-driver
|
||||
--log-opt
|
||||
--max-replicas
|
||||
--replicas
|
||||
--replicas-max-per-node
|
||||
--reserve-cpu
|
||||
@ -3804,7 +3811,7 @@ _docker_service_update_and_create() {
|
||||
return
|
||||
;;
|
||||
--mode)
|
||||
COMPREPLY=( $( compgen -W "global replicated" -- "$cur" ) )
|
||||
COMPREPLY=( $( compgen -W "global global-job replicated replicated-job" -- "$cur" ) )
|
||||
return
|
||||
;;
|
||||
esac
|
||||
@ -4348,6 +4355,9 @@ _docker_node_ls() {
|
||||
__docker_complete_nodes --cur "${cur##*=}" --id
|
||||
return
|
||||
;;
|
||||
label|node.label)
|
||||
return
|
||||
;;
|
||||
membership)
|
||||
COMPREPLY=( $( compgen -W "accepted pending" -- "${cur##*=}" ) )
|
||||
return
|
||||
@ -4364,7 +4374,7 @@ _docker_node_ls() {
|
||||
|
||||
case "$prev" in
|
||||
--filter|-f)
|
||||
COMPREPLY=( $( compgen -W "id label membership name role" -S = -- "$cur" ) )
|
||||
COMPREPLY=( $( compgen -W "id label membership name node.label role" -S = -- "$cur" ) )
|
||||
__docker_nospace
|
||||
return
|
||||
;;
|
||||
|
||||
@ -1343,7 +1343,7 @@ __docker_node_complete_ls_filters() {
|
||||
;;
|
||||
esac
|
||||
else
|
||||
opts=('id' 'label' 'membership' 'name' 'role')
|
||||
opts=('id' 'label' 'membership' 'name' 'node.label' 'role')
|
||||
_describe -t filter-opts "filter options" opts -qS "=" && ret=0
|
||||
fi
|
||||
|
||||
@ -2544,6 +2544,82 @@ __docker_volume_subcommand() {
|
||||
|
||||
# EO volume
|
||||
|
||||
# BO context
|
||||
|
||||
__docker_complete_contexts() {
|
||||
[[ $PREFIX = -* ]] && return 1
|
||||
integer ret=1
|
||||
declare -a contexts
|
||||
|
||||
contexts=(${(f)${:-"$(_call_program commands docker $docker_options context ls -q)"$'\n'}})
|
||||
|
||||
_describe -t context-list "context" contexts && ret=0
|
||||
return ret
|
||||
}
|
||||
|
||||
__docker_context_commands() {
|
||||
local -a _docker_context_subcommands
|
||||
_docker_context_subcommands=(
|
||||
"create:Create new context"
|
||||
"inspect:Display detailed information on one or more contexts"
|
||||
"list:List available contexts"
|
||||
"rm:Remove one or more contexts"
|
||||
"show:Print the current context"
|
||||
"update:Update a context"
|
||||
"use:Set the default context"
|
||||
)
|
||||
_describe -t docker-context-commands "docker context command" _docker_context_subcommands
|
||||
}
|
||||
|
||||
__docker_context_subcommand() {
|
||||
local -a _command_args opts_help
|
||||
local expl help="--help"
|
||||
integer ret=1
|
||||
|
||||
opts_help=("(: -)--help[Print usage]")
|
||||
|
||||
case "$words[1]" in
|
||||
(create)
|
||||
_arguments $(__docker_arguments) \
|
||||
$opts_help \
|
||||
"($help)--default-stack-orchestrator=[Default orchestrator for stack operations to use with this context]:default-stack-orchestrator:(swarm kubernetes all)" \
|
||||
"($help)--description=[Description of the context]:description:" \
|
||||
"($help)--docker=[Set the docker endpoint]:docker:" \
|
||||
"($help)--kubernetes=[Set the kubernetes endpoint]:kubernetes:" \
|
||||
"($help)--from=[Create context from a named context]:from:__docker_complete_contexts" \
|
||||
"($help -):name: " && ret=0
|
||||
;;
|
||||
(use)
|
||||
_arguments $(__docker_arguments) \
|
||||
$opts_help \
|
||||
"($help -)1:context:__docker_complete_contexts" && ret=0
|
||||
;;
|
||||
(inspect)
|
||||
_arguments $(__docker_arguments) \
|
||||
$opts_help \
|
||||
"($help -)1:context:__docker_complete_contexts" && ret=0
|
||||
;;
|
||||
(rm)
|
||||
_arguments $(__docker_arguments) \
|
||||
$opts_help \
|
||||
"($help -)1:context:__docker_complete_contexts" && ret=0
|
||||
;;
|
||||
(update)
|
||||
_arguments $(__docker_arguments) \
|
||||
$opts_help \
|
||||
"($help)--default-stack-orchestrator=[Default orchestrator for stack operations to use with this context]:default-stack-orchestrator:(swarm kubernetes all)" \
|
||||
"($help)--description=[Description of the context]:description:" \
|
||||
"($help)--docker=[Set the docker endpoint]:docker:" \
|
||||
"($help)--kubernetes=[Set the kubernetes endpoint]:kubernetes:" \
|
||||
"($help -):name:" && ret=0
|
||||
;;
|
||||
esac
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
# EO context
|
||||
|
||||
__docker_caching_policy() {
|
||||
oldp=( "$1"(Nmh+1) ) # 1 hour
|
||||
(( $#oldp ))
|
||||
@ -2631,6 +2707,23 @@ __docker_subcommand() {
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
(context)
|
||||
local curcontext="$curcontext" state
|
||||
_arguments $(__docker_arguments) \
|
||||
$opts_help \
|
||||
"($help -): :->command" \
|
||||
"($help -)*:: :->option-or-argument" && ret=0
|
||||
|
||||
case $state in
|
||||
(command)
|
||||
__docker_context_commands && ret=0
|
||||
;;
|
||||
(option-or-argument)
|
||||
curcontext=${curcontext%:*:*}:docker-${words[-1]}:
|
||||
__docker_context_subcommand && ret=0
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
(daemon)
|
||||
_arguments $(__docker_arguments) \
|
||||
$opts_help \
|
||||
|
||||
63
docker-bake.hcl
Normal file
63
docker-bake.hcl
Normal file
@ -0,0 +1,63 @@
|
||||
variable "VERSION" {
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "USE_GLIBC" {
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "STRIP_TARGET" {
|
||||
default = ""
|
||||
}
|
||||
|
||||
group "default" {
|
||||
targets = ["binary"]
|
||||
}
|
||||
|
||||
target "binary" {
|
||||
target = "binary"
|
||||
platforms = ["local"]
|
||||
output = ["build"]
|
||||
args = {
|
||||
BASE_VARIANT = USE_GLIBC != "" ? "buster" : "alpine"
|
||||
VERSION = VERSION
|
||||
GO_STRIP = STRIP_TARGET
|
||||
}
|
||||
}
|
||||
|
||||
target "dynbinary" {
|
||||
inherits = ["binary"]
|
||||
args = {
|
||||
GO_LINKMODE = "dynamic"
|
||||
}
|
||||
}
|
||||
|
||||
variable "GROUP_TOTAL" {
|
||||
default = "1"
|
||||
}
|
||||
|
||||
variable "GROUP_INDEX" {
|
||||
default = "0"
|
||||
}
|
||||
|
||||
function "platforms" {
|
||||
params = []
|
||||
result = ["linux/amd64", "linux/386", "linux/arm64", "linux/arm", "linux/ppc64le", "linux/s390x", "darwin/amd64", "darwin/arm64", "windows/amd64"]
|
||||
}
|
||||
|
||||
function "glen" {
|
||||
params = [platforms, GROUP_TOTAL]
|
||||
result = ceil(length(platforms)/GROUP_TOTAL)
|
||||
}
|
||||
|
||||
target "_all_platforms" {
|
||||
platforms = slice(platforms(), GROUP_INDEX*glen(platforms(), GROUP_TOTAL),min(length(platforms()), (GROUP_INDEX+1)*glen(platforms(), GROUP_TOTAL)))
|
||||
}
|
||||
|
||||
target "cross" {
|
||||
inherits = ["binary", "_all_platforms"]
|
||||
}
|
||||
|
||||
target "dynbinary-cross" {
|
||||
inherits = ["dynbinary", "_all_platforms"]
|
||||
}
|
||||
@ -38,11 +38,6 @@ build_linter_image:
|
||||
# build dockerfile from stdin so that we don't send the build-context; source is bind-mounted in the development environment
|
||||
cat ./dockerfiles/Dockerfile.lint | docker build ${DOCKER_BUILD_ARGS} --build-arg=GO_VERSION -t $(LINTER_IMAGE_NAME) -
|
||||
|
||||
.PHONY: build_cross_image
|
||||
build_cross_image:
|
||||
# build dockerfile from stdin so that we don't send the build-context; source is bind-mounted in the development environment
|
||||
cat ./dockerfiles/Dockerfile.cross | docker build ${DOCKER_BUILD_ARGS} --build-arg=GO_VERSION -t $(CROSS_IMAGE_NAME) -
|
||||
|
||||
.PHONY: build_shell_validate_image
|
||||
build_shell_validate_image:
|
||||
# build dockerfile from stdin so that we don't send the build-context; source is bind-mounted in the development environment
|
||||
@ -80,22 +75,10 @@ test-unit: build_docker_image ## run unit tests (using go test)
|
||||
.PHONY: test ## run unit and e2e tests
|
||||
test: test-unit test-e2e
|
||||
|
||||
.PHONY: cross
|
||||
cross: build_cross_image ## build the CLI for macOS and Windows
|
||||
$(DOCKER_RUN) $(CROSS_IMAGE_NAME) make cross
|
||||
|
||||
.PHONY: binary-windows
|
||||
binary-windows: build_cross_image ## build the CLI for Windows
|
||||
$(DOCKER_RUN) $(CROSS_IMAGE_NAME) make $@
|
||||
|
||||
.PHONY: plugins-windows
|
||||
plugins-windows: build_cross_image ## build the example CLI plugins for Windows
|
||||
$(DOCKER_RUN) $(CROSS_IMAGE_NAME) make $@
|
||||
|
||||
.PHONY: binary-osx
|
||||
binary-osx: build_cross_image ## build the CLI for macOS
|
||||
$(DOCKER_RUN) $(CROSS_IMAGE_NAME) make $@
|
||||
|
||||
.PHONY: plugins-osx
|
||||
plugins-osx: build_cross_image ## build the example CLI plugins for macOS
|
||||
$(DOCKER_RUN) $(CROSS_IMAGE_NAME) make $@
|
||||
@ -120,9 +103,6 @@ fmt: ## run gofmt
|
||||
vendor: build_docker_image vendor.conf ## download dependencies (vendor/) listed in vendor.conf
|
||||
$(DOCKER_RUN) -it $(DEV_DOCKER_IMAGE_NAME) make vendor
|
||||
|
||||
dynbinary: build_cross_image ## build the CLI dynamically linked
|
||||
$(DOCKER_RUN) -it $(CROSS_IMAGE_NAME) make dynbinary
|
||||
|
||||
.PHONY: authors
|
||||
authors: ## generate AUTHORS file from git history
|
||||
$(DOCKER_RUN) -it $(DEV_DOCKER_IMAGE_NAME) make authors
|
||||
|
||||
@ -52,6 +52,7 @@ Status | Feature
|
||||
-----------|------------------------------------------------------------------------------------------------------------------------------------|------------|------------
|
||||
Deprecated | [Pulling images from non-compliant image registries](#pulling-images-from-non-compliant-image-registries) | v20.10 | -
|
||||
Deprecated | [Linux containers on Windows (LCOW)](#linux-containers-on-windows-lcow-experimental) | v20.10 | -
|
||||
Deprecated | [BLKIO weight options with cgroups v1](#blkio-weight-options–with-cgroups-v1) | v20.10 | -
|
||||
Deprecated | [Kernel memory limit](#kernel-memory-limit) | v20.10 | -
|
||||
Deprecated | [Classic Swarm and overlay networks using external key/value stores](#classic-swarm-and-overlay-networks-using-cluster-store) | v20.10 | -
|
||||
Deprecated | [Support for the legacy `~/.dockercfg` configuration file for authentication](#support-for-legacy-dockercfg-configuration-files) | v20.10 | -
|
||||
@ -140,6 +141,16 @@ now stopped in favor of running docker natively on Linux in WSL2.
|
||||
Developers who want to run Linux workloads on a Windows host are encouraged to use
|
||||
[Docker Desktop with WSL2](https://docs.docker.com/docker-for-windows/wsl/) instead.
|
||||
|
||||
### BLKIO weight options with cgroups v1
|
||||
|
||||
**Deprecated in Release: v20.10**
|
||||
|
||||
Specifying blkio weight (`docker run --blkio-weight` and `docker run --blkio-weight-device`)
|
||||
is now marked as deprecated when using cgroups v1 because the corresponding features
|
||||
were [removed in Linux kernel v5.0 and up](https://github.com/torvalds/linux/commit/f382fb0bcef4c37dc049e9f6963e3baf204d815c).
|
||||
When using cgroups v2, the `--blkio-weight` options are implemented using
|
||||
[`io.weight](https://github.com/torvalds/linux/blob/v5.0/Documentation/admin-guide/cgroup-v2.rst#io).
|
||||
|
||||
### Kernel memory limit
|
||||
|
||||
**Deprecated in Release: v20.10**
|
||||
|
||||
@ -60,6 +60,7 @@ The currently supported filters are:
|
||||
|
||||
* [id](#id)
|
||||
* [label](#label)
|
||||
* [node.label](#nodelabel)
|
||||
* [membership](#membership)
|
||||
* [name](#name)
|
||||
* [role](#role)
|
||||
@ -77,7 +78,10 @@ ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
|
||||
|
||||
#### label
|
||||
|
||||
The `label` filter matches nodes based on engine labels and on the presence of a `label` alone or a `label` and a value. Node labels are currently not used for filtering.
|
||||
The `label` filter matches nodes based on engine labels and on the presence of a
|
||||
`label` alone or a `label` and a value. Engine labels are configured in
|
||||
the [daemon configuration](dockerd.md#daemon-configuration-file). To filter on
|
||||
Swarm `node` labels, use [`node.label` instead](#nodelabel).
|
||||
|
||||
The following filter matches nodes with the `foo` label regardless of its value.
|
||||
|
||||
@ -88,6 +92,42 @@ ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
|
||||
1bcef6utixb0l0ca7gxuivsj0 swarm-worker2 Ready Active
|
||||
```
|
||||
|
||||
#### node.label
|
||||
|
||||
The `node.label` filter matches nodes based on node labels and on the presence
|
||||
of a `node.label` alone or a `node.label` and a value.
|
||||
|
||||
The following filter updates nodes to have a `region` node label:
|
||||
|
||||
```console
|
||||
$ docker node update --label-add region=region-a swarm-test-01
|
||||
$ docker node update --label-add region=region-a swarm-test-02
|
||||
$ docker node update --label-add region=region-b swarm-test-03
|
||||
$ docker node update --label-add region=region-b swarm-test-04
|
||||
```
|
||||
|
||||
Show all nodes that have a `region` node label set:
|
||||
|
||||
```console
|
||||
$ docker node ls --filter node.label=region
|
||||
|
||||
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
|
||||
yg550ettvsjn6g6t840iaiwgb * swarm-test-01 Ready Active Leader 20.10.2
|
||||
2lm9w9kbepgvkzkkeyku40e65 swarm-test-02 Ready Active Reachable 20.10.2
|
||||
hc0pu7ntc7s4uvj4pv7z7pz15 swarm-test-03 Ready Active Reachable 20.10.2
|
||||
n41b2cijmhifxxvz56vwrs12q swarm-test-04 Ready Active 20.10.2
|
||||
```
|
||||
|
||||
Show all nodes that have a `region` node label, with value `region-a`:
|
||||
|
||||
```console
|
||||
$ docker node ls --filter node.label=region=region-a
|
||||
|
||||
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
|
||||
yg550ettvsjn6g6t840iaiwgb * swarm-test-01 Ready Active Leader 20.10.2
|
||||
2lm9w9kbepgvkzkkeyku40e65 swarm-test-02 Ready Active Reachable 20.10.2
|
||||
```
|
||||
|
||||
#### membership
|
||||
|
||||
The `membership` filter matches nodes based on the presence of a `membership` and a value
|
||||
|
||||
@ -76,7 +76,7 @@ listed.
|
||||
|
||||
### Push all tags of an image
|
||||
|
||||
Use the `-a` (or `--all-tags`) option to push To push all tags of a local image.
|
||||
Use the `-a` (or `--all-tags`) option to push all tags of a local image.
|
||||
|
||||
The following example creates multiple tags for an image, and pushes all those
|
||||
tags to Docker Hub.
|
||||
|
||||
@ -58,13 +58,33 @@ The main process inside the container referenced under the link `redis` will rec
|
||||
|
||||
### Remove all stopped containers
|
||||
|
||||
```bash
|
||||
$ docker rm $(docker ps -a -q)
|
||||
Use the [`docker container prune`](container_prune.md) command to remove all
|
||||
stopped containers, or refer to the [`docker system prune`](system_prune.md)
|
||||
command to remove unused containers in addition to other Docker resources, such
|
||||
as (unused) images and networks.
|
||||
|
||||
Alternatively, you can use the `docker ps` with the `-q` / `--quiet` option to
|
||||
generate a list of container IDs to remove, and use that list as argument for
|
||||
the `docker rm` command.
|
||||
|
||||
Combining commands can be more flexible, but is less portable as it depends
|
||||
on features provided by the shell, and the exact syntax may differ depending on
|
||||
what shell is used. To use this approach on Windows, consider using PowerShell
|
||||
or Bash.
|
||||
|
||||
The example below uses `docker ps -q` to print the IDs of all containers that
|
||||
have exited (`--filter status=exited`), and removes those containers with
|
||||
the `docker rm` command:
|
||||
|
||||
```console
|
||||
$ docker rm $(docker ps --filter status=exited -q)
|
||||
```
|
||||
|
||||
This command deletes all stopped containers. The command
|
||||
`docker ps -a -q` above returns all existing container IDs and passes them to
|
||||
the `rm` command which deletes them. Running containers are not deleted.
|
||||
Or, using the `xargs` Linux utility;
|
||||
|
||||
```console
|
||||
$ docker ps --filter status=exited -q | xargs docker rm
|
||||
```
|
||||
|
||||
### Remove a container and its volumes
|
||||
|
||||
|
||||
@ -43,7 +43,7 @@ ID NAME MODE REPLICAS IMAGE
|
||||
c8wgl7q4ndfd frontend replicated 5/5 nginx:alpine
|
||||
dmu1ept4cxcf redis replicated 3/3 redis:3.0.6
|
||||
iwe3278osahj mongo global 7/7 mongo:3.3
|
||||
hh08h9uu8uwr job replicated-job 1/1 (3/5 completed) nginx:latest
|
||||
hh08h9uu8uwr job replicated-job 1/1 (3/5 completed) nginx:latest
|
||||
```
|
||||
|
||||
The `REPLICAS` column shows both the *actual* and *desired* number of tasks for
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
---
|
||||
description: "Configure containers at runtime"
|
||||
keywords: "docker, run, configure, runtime"
|
||||
redirect_from:
|
||||
- /reference/run/
|
||||
---
|
||||
|
||||
<!-- This file is maintained within the docker/cli GitHub
|
||||
@ -1738,7 +1740,7 @@ volume mounted on the host).
|
||||
|
||||
The `container-dest` must always be an absolute path such as `/src/docs`.
|
||||
The `host-src` can either be an absolute path or a `name` value. If you
|
||||
supply an absolute path for the `host-dir`, Docker bind-mounts to the path
|
||||
supply an absolute path for the `host-src`, Docker bind-mounts to the path
|
||||
you specify. If you supply a `name`, Docker creates a named volume by that `name`.
|
||||
|
||||
A `name` value must start with an alphanumeric character,
|
||||
|
||||
@ -1,8 +1,11 @@
|
||||
package context
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"gotest.tools/v3/assert"
|
||||
"gotest.tools/v3/golden"
|
||||
"gotest.tools/v3/icmd"
|
||||
)
|
||||
@ -19,3 +22,73 @@ func TestContextList(t *testing.T) {
|
||||
})
|
||||
golden.Assert(t, result.Stdout(), "context-ls.golden")
|
||||
}
|
||||
|
||||
func TestContextImportNoTLS(t *testing.T) {
|
||||
d, _ := ioutil.TempDir("", "")
|
||||
defer func() {
|
||||
os.RemoveAll(d)
|
||||
}()
|
||||
cmd := icmd.Command("docker", "context", "import", "remote", "./testdata/test-dockerconfig.tar")
|
||||
cmd.Env = append(cmd.Env,
|
||||
"DOCKER_CONFIG="+d,
|
||||
)
|
||||
icmd.RunCmd(cmd).Assert(t, icmd.Success)
|
||||
|
||||
cmd = icmd.Command("docker", "context", "ls")
|
||||
cmd.Env = append(cmd.Env,
|
||||
"DOCKER_CONFIG="+d,
|
||||
"KUBECONFIG=./testdata/test-kubeconfig", // Allows reuse of context-ls.golden
|
||||
)
|
||||
result := icmd.RunCmd(cmd).Assert(t, icmd.Success)
|
||||
golden.Assert(t, result.Stdout(), "context-ls.golden")
|
||||
}
|
||||
|
||||
func TestContextImportTLS(t *testing.T) {
|
||||
d, _ := ioutil.TempDir("", "")
|
||||
defer func() {
|
||||
os.RemoveAll(d)
|
||||
}()
|
||||
cmd := icmd.Command("docker", "context", "import", "test", "./testdata/test-dockerconfig-tls.tar")
|
||||
cmd.Env = append(cmd.Env,
|
||||
"DOCKER_CONFIG="+d,
|
||||
)
|
||||
icmd.RunCmd(cmd).Assert(t, icmd.Success)
|
||||
|
||||
cmd = icmd.Command("docker", "context", "ls")
|
||||
cmd.Env = append(cmd.Env,
|
||||
"DOCKER_CONFIG="+d,
|
||||
)
|
||||
result := icmd.RunCmd(cmd).Assert(t, icmd.Success)
|
||||
golden.Assert(t, result.Stdout(), "context-ls-tls.golden")
|
||||
|
||||
b, err := ioutil.ReadFile(d + "/contexts/tls/9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08/kubernetes/key.pem")
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, string(b), `-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpAIBAAKCAQEArQk77K5sgrQYY6HiQ1y7AC+67HrRB36oEvR+Fq60RsFcc3cZ
|
||||
xAvMkRSBPjQyskjdYY7kfykGHhfJxGKopb3cDJx3eDBxjgAniwnnOMmHVWbf8Eik
|
||||
o0sNxkgzQPGq83nL3QvVxm3xgqe4nlTdR/Swoq6Pv0oaVYvPPMnaZIF89SJ/wlNT
|
||||
myCs6Uq00dICi20II+M2Nw9b+EVEK4ENl+SlrsK7iuoBIh/H0ZghxOthO9J/HeBb
|
||||
hmM4wcs1OonhPDYKHEaChYA7/Q3/8OBp3bAdlQJ1ziyP3ROAKHL2NwwkGZ8o8HP8
|
||||
u0ex/NAb8w5J5WNePqYQd/sqfisfNpA5VIKcEQIDAQABAoIBABLo4W2aGi2mdMve
|
||||
kxV9esoobSsOuO0ywDdiFK1x5i2dT/cmWuB70Z1BOmaL2cZ2BAt3TC1BVHPRcbFO
|
||||
ftOuDfAq4Tt3P9Ge3rNpH6WrEGka1voxVhyqRRUYKtG8F0yIUOkVNAV9WllG7vwO
|
||||
ligY63y7yuXCuWID51/jR0SYiglXz6G4gcJKFXtugXXiLUIg08GVWkwOsrACC+hR
|
||||
mhcHly1926VhN5+ozjNU/GZ1LaTuK6erBZakH5bqlN97s5rrk0ZRwk/JtnkoRRdI
|
||||
cq0918Za2vqGDHZ3MqLttL52YfDXPIEJPwlFdvC/+sXK2NhUB/xY4yuliU3sY0sf
|
||||
XsIvIWECgYEAwD8AnZI0hnGv8hc6zJppHFRwhrtLZ+09SJwPv5Y4wxuuk5dzNkpf
|
||||
xCNo5hjSVYA1MMmWG8p/sEXo2IyCT8sWDNCn9kieTXihxRxbj88Y2qA5O4N46Zy4
|
||||
kPngjkP5PPDMkwaQQgUr9LvlWS7P6OJkH18ZN8s3QhMaKcHu9FFT44UCgYEA5mte
|
||||
mMSDf9hUK3IK+yrGX62qc2H+ecXN3Zf3nehyiz+dX4ZXhBwBkwJ/mHvuAZPfoFUN
|
||||
Xg6cdyWFJg9ynm45JXnDjmYPGmFLn0mP3Mje/+SbbW2fdFWHJW/maqj4uUqqgQd+
|
||||
pGNzKXq34MzDrpsqIJ7AHu3LYVMOoLAVqC7LXh0CgYEAnLF9ZfFqQH7fgvouIeBl
|
||||
dgLZKOf2AUJcJheVunnN0DF67K+P55tdTTfzY0CuB6SVNivI3uQBiYKh1AdKm5ET
|
||||
auSTUmlEJi8B4/BGLQQG5QOdQoXZgsgLo5cX0b1To7k9dUTvRfCDMFoKCNPgAJiu
|
||||
NOfFXTWU15VMSObaRmcXciUCgYEA5e1cXwsxwUAodZX+eTXs8ArHHQ47Nl55GFeN
|
||||
wufybRuUuX7AE9cyhvUmSA3aqX5a144noaTo40fwftNJZ+jLY6cGyjDzfzp5kMCC
|
||||
KynSxPzlUCPkytyR2Hy6K9LjJ1rnm4vUBswqXcjUdiE+Xxz8w8JGKlbV7Q9JeHVd
|
||||
lw7i5s0CgYAn9T9ySI3xCbrUa/XV/ZY2hopUdH5CDPeTd2eH+L+lctkD9nlzLrpj
|
||||
qij+jaEUweymNx0uttgv02J3DYcIIvVq3RNAwORy5Mp9KasHmjbW2xq+HAq5yFOO
|
||||
1ma82F5zeUl+bKqjMRCY8IVZ349VxRZtb2RVVEKyVswb7HmKp6gGbA==
|
||||
-----END RSA PRIVATE KEY-----
|
||||
`)
|
||||
}
|
||||
|
||||
3
e2e/context/testdata/context-ls-notls.golden
vendored
Normal file
3
e2e/context/testdata/context-ls-notls.golden
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
NAME DESCRIPTION DOCKER ENDPOINT KUBERNETES ENDPOINT ORCHESTRATOR
|
||||
default * Current DOCKER_HOST based configuration unix:///var/run/docker.sock swarm
|
||||
remote my remote cluster ssh://someserver https://someserver (default) kubernetes
|
||||
3
e2e/context/testdata/context-ls-tls.golden
vendored
Normal file
3
e2e/context/testdata/context-ls-tls.golden
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
NAME DESCRIPTION DOCKER ENDPOINT KUBERNETES ENDPOINT ORCHESTRATOR
|
||||
default * Current DOCKER_HOST based configuration unix:///var/run/docker.sock swarm
|
||||
test unix:///var/run/docker.sock https://kubernetes.docker.internal:6443 (default) swarm
|
||||
BIN
e2e/context/testdata/test-dockerconfig-tls.tar
vendored
Normal file
BIN
e2e/context/testdata/test-dockerconfig-tls.tar
vendored
Normal file
Binary file not shown.
BIN
e2e/context/testdata/test-dockerconfig.tar
vendored
Normal file
BIN
e2e/context/testdata/test-dockerconfig.tar
vendored
Normal file
Binary file not shown.
@ -504,13 +504,13 @@ and foreground Docker containers.
|
||||
**--network**=*type*
|
||||
Set the Network mode for the container. Supported values are:
|
||||
|
||||
| Value | Description |
|
||||
|:----------------------------|:-----------------------------------------------------------------------------------------|
|
||||
| **none** | No networking in the container. |
|
||||
| **bridge** | Connect the container to the default Docker bridge via veth interfaces. |
|
||||
| **host** | Use the host's network stack inside the container. |
|
||||
| **container:**_name_|_id_ | Use the network stack of another container, specified via its _name_ or _id_. |
|
||||
| _network-name_|_network-id_ | Connects the container to a user created network (using `docker network create` command) |
|
||||
| Value | Description |
|
||||
|:-----------------------------|:-----------------------------------------------------------------------------------------|
|
||||
| **none** | No networking in the container. |
|
||||
| **bridge** | Connect the container to the default Docker bridge via veth interfaces. |
|
||||
| **host** | Use the host's network stack inside the container. |
|
||||
| **container:**_name_\|_id_ | Use the network stack of another container, specified via its _name_ or _id_. |
|
||||
| _network-name_\|_network-id_ | Connects the container to a user created network (using `docker network create` command) |
|
||||
|
||||
Default is **bridge**.
|
||||
|
||||
|
||||
@ -18,5 +18,5 @@ for FILE in *.md; do
|
||||
continue
|
||||
fi
|
||||
mkdir -p "./man${num}"
|
||||
md2man -in "$FILE" -out "./man${num}/${name}"
|
||||
go-md2man -in "$FILE" -out "./man${num}/${name}"
|
||||
done
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
#!/usr/bin/env bash
|
||||
#!/usr/bin/env sh
|
||||
set -eu
|
||||
|
||||
TARGET=${TARGET:-"build"}
|
||||
|
||||
PLATFORM=${PLATFORM:-}
|
||||
VERSION=${VERSION:-"unknown-version"}
|
||||
VERSION=${VERSION:-$(git describe --match 'v[0-9]*' --dirty='.m' --always --tags | sed 's/^v//' 2>/dev/null || echo "unknown-version" )}
|
||||
GITCOMMIT=${GITCOMMIT:-$(git rev-parse --short HEAD 2> /dev/null || true)}
|
||||
BUILDTIME=${BUILDTIME:-$(date -u +"%Y-%m-%dT%H:%M:%SZ")}
|
||||
|
||||
@ -20,15 +22,15 @@ export LDFLAGS="\
|
||||
${LDFLAGS:-} \
|
||||
"
|
||||
|
||||
GOOS="${GOOS:-$(go env GOHOSTOS)}"
|
||||
GOARCH="${GOARCH:-$(go env GOHOSTARCH)}"
|
||||
GOOS="$(go env GOOS)"
|
||||
GOARCH="$(go env GOARCH)"
|
||||
if [ "${GOARCH}" = "arm" ]; then
|
||||
GOARM="${GOARM:-$(go env GOHOSTARM)}"
|
||||
GOARM="$(go env GOARM)"
|
||||
fi
|
||||
|
||||
TARGET="build/docker-$GOOS-$GOARCH"
|
||||
TARGET="$TARGET/docker-${GOOS}-${GOARCH}"
|
||||
if [ "${GOARCH}" = "arm" ] && [ -n "${GOARM}" ]; then
|
||||
TARGET="${TARGET}-v${GOARM}"
|
||||
TARGET="${TARGET}-v${GOARM}"
|
||||
fi
|
||||
|
||||
if [ "${GOOS}" = "windows" ]; then
|
||||
|
||||
@ -1,14 +1,80 @@
|
||||
#!/usr/bin/env bash
|
||||
#!/usr/bin/env sh
|
||||
#
|
||||
# Build a static binary for the host OS/ARCH
|
||||
#
|
||||
|
||||
set -eu -o pipefail
|
||||
set -eu
|
||||
|
||||
source ./scripts/build/.variables
|
||||
: "${CGO_ENABLED=}"
|
||||
: "${GO_LINKMODE=static}"
|
||||
: "${GO_BUILDMODE=}"
|
||||
: "${GO_BUILDTAGS=}"
|
||||
: "${GO_STRIP=}"
|
||||
|
||||
echo "Building statically linked $TARGET"
|
||||
export CGO_ENABLED=0
|
||||
go build -o "${TARGET}" --ldflags "${LDFLAGS}" "${SOURCE}"
|
||||
. ./scripts/build/.variables
|
||||
|
||||
ln -sf "$(basename "${TARGET}")" build/docker
|
||||
if [ -z "$CGO_ENABLED" ]; then
|
||||
case "$(go env GOOS)" in
|
||||
linux)
|
||||
case "$(go env GOARCH)" in
|
||||
amd64|arm64|arm|s390x)
|
||||
CGO_ENABLED=1
|
||||
;;
|
||||
*)
|
||||
CGO_ENABLED=0
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
darwin|windows)
|
||||
CGO_ENABLED=1
|
||||
;;
|
||||
*)
|
||||
CGO_ENABLED=0
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
export CGO_ENABLED
|
||||
if [ "$CGO_ENABLED" = "1" ] && [ "$(go env GOOS)" != "windows" ]; then
|
||||
case "$(go env GOARCH)" in
|
||||
mips*|ppc64)
|
||||
# pie build mode is not supported on mips architectures
|
||||
;;
|
||||
*)
|
||||
GO_BUILDMODE="-buildmode=pie"
|
||||
;;
|
||||
esac
|
||||
GO_BUILDTAGS="$GO_BUILDTAGS pkcs11"
|
||||
fi
|
||||
|
||||
if [ "$CGO_ENABLED" = "1" ] && [ "$GO_LINKMODE" = "static" ] && [ "$(go env GOOS)" = "linux" ]; then
|
||||
LDFLAGS="$LDFLAGS -extldflags -static"
|
||||
fi
|
||||
|
||||
if [ -n "$GO_STRIP" ]; then
|
||||
LDFLAGS="$LDFLAGS -s -w"
|
||||
fi
|
||||
|
||||
if [ "$(go env GOOS)" = "windows" ]; then
|
||||
# Generate a Windows file version of the form major,minor,patch,build
|
||||
VERSION_QUAD=$(printf "%s" "$VERSION" | sed -re 's/^([0-9.]*).*$/\1/' | tr . , | sed -re 's/^[0-9]+$/\0,0/' | sed -re 's/^[0-9]+,[0-9]+$/\0,0/' | sed -re 's/^[0-9]+,[0-9]+,[0-9]+$/\0,0/')
|
||||
|
||||
set --
|
||||
[ -n "$VERSION" ] && set -- "$@" -D "DOCKER_VERSION=\"$VERSION\""
|
||||
[ -n "$VERSION_QUAD" ] && set -- "$@" -D "DOCKER_VERSION_QUAD=$VERSION_QUAD"
|
||||
[ -n "$GITCOMMIT" ] && set -- "$@" -D "DOCKER_COMMIT=\"$GITCOMMIT\""
|
||||
|
||||
windres=$($(go env CC) --print-prog-name=windres)
|
||||
|
||||
target="$(dirname "$0")/../../cli/winresources/rsrc_$(go env GOARCH).syso"
|
||||
mkdir -p "$(dirname "${target}")"
|
||||
"$windres" -i "$(dirname "$0")/../winresources/docker.rc" -o "$target" "$@"
|
||||
echo "package winresources" > "$(dirname "${target}")/stub_windows.go"
|
||||
fi
|
||||
|
||||
echo "Building $GO_LINKMODE $(basename "${TARGET}")"
|
||||
|
||||
export GO111MODULE=auto
|
||||
|
||||
go build -o "${TARGET}" -tags "${GO_BUILDTAGS}" --ldflags "${LDFLAGS}" ${GO_BUILDMODE} "${SOURCE}"
|
||||
|
||||
ln -sf "$(basename "${TARGET}")" "$(dirname "${TARGET}")/docker"
|
||||
|
||||
@ -1,33 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Build a binary for all supported platforms
|
||||
#
|
||||
|
||||
set -eu -o pipefail
|
||||
|
||||
BUILDDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
export SHELL=bash
|
||||
|
||||
jobs=(
|
||||
"$BUILDDIR/windows" \
|
||||
"$BUILDDIR/osx" \
|
||||
"GOOS=linux GOARCH=amd64 $BUILDDIR/binary" \
|
||||
"GOOS=linux GOARCH=arm $BUILDDIR/binary" \
|
||||
"GOOS=linux GOARCH=ppc64le $BUILDDIR/binary" \
|
||||
"GOOS=linux GOARCH=s390x $BUILDDIR/binary" \
|
||||
)
|
||||
|
||||
# Outside of circleCI run all at once. On circleCI run two at a time because
|
||||
# each container has access to two cores.
|
||||
group=${CROSS_GROUP-"all"}
|
||||
|
||||
if [ "$group" = "all" ]; then
|
||||
|
||||
echo "Building binaries for all platforms"
|
||||
parallel ::: "${jobs[@]}"
|
||||
exit 0
|
||||
|
||||
fi
|
||||
|
||||
declare -i start="$group*2"
|
||||
parallel ::: "${jobs[@]:$start:2}"
|
||||
@ -1,24 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Build a dynamically linked binary for the host OS/ARCH
|
||||
#
|
||||
|
||||
set -eu -o pipefail
|
||||
|
||||
source ./scripts/build/.variables
|
||||
|
||||
echo "Building dynamically linked $TARGET"
|
||||
export CGO_ENABLED=1
|
||||
case "$(go env GOARCH)" in
|
||||
mips*|ppc64)
|
||||
# pie build mode is not supported on mips architectures
|
||||
GO_BUILDMODE=""
|
||||
;;
|
||||
*)
|
||||
GO_BUILDMODE="-buildmode=pie"
|
||||
;;
|
||||
esac
|
||||
|
||||
go build -o "${TARGET}" -tags pkcs11 --ldflags "${LDFLAGS}" ${GO_BUILDMODE} "${SOURCE}"
|
||||
|
||||
ln -sf "$(basename "${TARGET}")" build/docker
|
||||
@ -1,22 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Build an osx binary from linux
|
||||
#
|
||||
|
||||
set -eu -o pipefail
|
||||
|
||||
source ./scripts/build/.variables
|
||||
|
||||
export CGO_ENABLED=1
|
||||
export GOOS=darwin
|
||||
export GOARCH=amd64
|
||||
export CC=o64-clang
|
||||
export CXX=o64-clang++
|
||||
export LDFLAGS="$LDFLAGS -linkmode external -s"
|
||||
export LDFLAGS_STATIC_DOCKER='-extld='${CC}
|
||||
|
||||
# Override TARGET
|
||||
TARGET="build/docker-$GOOS-$GOARCH"
|
||||
|
||||
echo "Building $TARGET"
|
||||
go build -o "${TARGET}" -tags pkcs11 --ldflags "${LDFLAGS}" "${SOURCE}"
|
||||
@ -1,23 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Build a windows binary from linux
|
||||
#
|
||||
|
||||
set -eu -o pipefail
|
||||
|
||||
source ./scripts/build/.variables
|
||||
|
||||
export CC=x86_64-w64-mingw32-gcc
|
||||
export CGO_ENABLED=1
|
||||
export GOOS=windows
|
||||
export GOARCH=amd64
|
||||
|
||||
# Override TARGET
|
||||
TARGET="build/docker-$GOOS-$GOARCH.exe"
|
||||
|
||||
echo "Generating windows resources"
|
||||
go generate ./cli/winresources
|
||||
|
||||
echo "Building $TARGET"
|
||||
# TODO: -tags pkcs11
|
||||
go build -o "${TARGET}" --ldflags "${LDFLAGS}" "${SOURCE}"
|
||||
@ -4,9 +4,9 @@ set -eu -o pipefail
|
||||
|
||||
mkdir -p ./man/man1
|
||||
|
||||
if ! command -v md2man &> /dev/null; then
|
||||
if ! command -v go-md2man &> /dev/null; then
|
||||
# yay, go install creates a binary named "v2" ¯\_(ツ)_/¯
|
||||
go build -o "/go/bin/md2man" ./vendor/github.com/cpuguy83/go-md2man/v2
|
||||
go build -o "/go/bin/go-md2man" ./vendor/github.com/cpuguy83/go-md2man/v2
|
||||
fi
|
||||
|
||||
# Generate man pages from cobra commands
|
||||
|
||||
@ -1,45 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Compile the Windows resources into the sources
|
||||
#
|
||||
|
||||
set -eu -o pipefail
|
||||
|
||||
SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
# shellcheck source=/go/src/github.com/docker/cli/scripts/build/.variables
|
||||
source "$SCRIPTDIR"/../build/.variables
|
||||
|
||||
RESOURCES=$SCRIPTDIR/../winresources
|
||||
|
||||
TEMPDIR=$(mktemp -d)
|
||||
trap 'rm -rf $TEMPDIR' EXIT
|
||||
|
||||
if [ "$(go env GOHOSTOS)" = "windows" ]; then
|
||||
WINDRES=windres
|
||||
else
|
||||
# Cross compiling
|
||||
WINDRES=x86_64-w64-mingw32-windres
|
||||
fi
|
||||
|
||||
# Generate a Windows file version of the form major,minor,patch,build (with any part optional)
|
||||
VERSION_QUAD=$(printf "%s" "$VERSION" | sed -re 's/^([0-9.]*).*$/\1/' | tr . ,)
|
||||
|
||||
# Pass version and commit information into the resource compiler
|
||||
defs=
|
||||
[ -n "$VERSION" ] && defs+=( "-D DOCKER_VERSION=\"$VERSION\"")
|
||||
[ -n "$VERSION_QUAD" ] && defs+=( "-D DOCKER_VERSION_QUAD=$VERSION_QUAD")
|
||||
[ -n "$GITCOMMIT" ] && defs+=( "-D DOCKER_COMMIT=\"$GITCOMMIT\"")
|
||||
|
||||
makeres() {
|
||||
# shellcheck disable=SC2086
|
||||
"$WINDRES" \
|
||||
-i "$RESOURCES/$1" \
|
||||
-o "$3" \
|
||||
-F "$2" \
|
||||
--use-temp-file \
|
||||
-I "$TEMPDIR" \
|
||||
${defs[*]}
|
||||
}
|
||||
|
||||
makeres docker.rc pe-x86-64 rsrc_amd64.syso
|
||||
makeres docker.rc pe-i386 rsrc_386.syso
|
||||
@ -1,5 +1,4 @@
|
||||
cloud.google.com/go ceeb313ad77b789a7fa5287b36a1d127b69b7093 # v0.44.3
|
||||
github.com/agl/ed25519 5312a61534124124185d41f09206b9fef1d88403
|
||||
github.com/Azure/go-ansiterm d6e3b3328b783f23731bc4d058875b0371ff8109
|
||||
github.com/beorn7/perks 37c8de3658fcb183f997c4e13e8337516ab753e6 # v1.0.1
|
||||
github.com/cespare/xxhash/v2 d7df74196a9e781ede915320c11c378c1b2f3a1f # v2.1.1
|
||||
@ -14,8 +13,8 @@ github.com/creack/pty 2a38352e8b4d7ab6c336eef107e4
|
||||
github.com/davecgh/go-spew 8991bc29aa16c548c550c7ff78260e27b9ab7c73 # v1.1.1
|
||||
github.com/docker/compose-on-kubernetes 78e6a00beda64ac8ccb9fec787e601fe2ce0d5bb # v0.5.0-alpha1
|
||||
github.com/docker/distribution 0d3efadf0154c2b8a4e7b6621fff9809655cc580
|
||||
github.com/docker/docker f0014860c1b3345e1fcc7ed81c491298de2633fb # v20.10.1
|
||||
github.com/docker/docker-credential-helpers 54f0238b6bf101fc3ad3b34114cb5520beb562f5 # v0.6.3
|
||||
github.com/docker/docker 46229ca1d815cfd4b50eb377ac75ad8300e13a85
|
||||
github.com/docker/docker-credential-helpers 38bea2ce277ad0c9d2a6230692b0606ca5286526
|
||||
github.com/docker/go d30aec9fd63c35133f8f79c3412ad91a3b08be06 # Contains a customized version of canonical/json and is used by Notary. The package is periodically rebased on current Go versions.
|
||||
github.com/docker/go-connections 7395e3f8aa162843a74ed6d48e79627d9792ac55 # v0.4.0
|
||||
github.com/docker/go-events e31b211e4f1cd09aa76fe4ac244571fab96ae47f
|
||||
@ -68,7 +67,7 @@ github.com/shurcooL/sanitized_anchor_name 7bfe4c7ecddb3666a94b053b422c
|
||||
github.com/sirupsen/logrus 6699a89a232f3db797f2e280639854bbc4b89725 # v1.7.0
|
||||
github.com/spf13/cobra 86f8bfd7fef868a174e1b606783bd7f5c82ddf8f # v1.1.1
|
||||
github.com/spf13/pflag 2e9d26c8c37aae03e3f9d4e90b7116f5accb7cab # v1.0.5
|
||||
github.com/theupdateframework/notary d6e1431feb32348e0650bf7551ac5cffd01d857b # v0.6.1
|
||||
github.com/theupdateframework/notary bf96a202a09a312ae005cd312fc06ff4d2c166ce # v0.7.0-21-gbf96a202
|
||||
github.com/tonistiigi/fsutil 0834f99b7b85462efb69b4f571a4fa3ca7da5ac9
|
||||
github.com/tonistiigi/go-rosetta f79598599c5d34ea253b56a1d7c89bc6a96de7db
|
||||
github.com/tonistiigi/units 6950e57a87eaf136bbe44ef2ec8e75b9e3569de2
|
||||
@ -80,7 +79,7 @@ golang.org/x/crypto c1f2f97bffc9c53fc40a1a28a5b4
|
||||
golang.org/x/net ab34263943818b32f575efc978a3d24e80b04bd7
|
||||
golang.org/x/oauth2 bf48bf16ab8d622ce64ec6ce98d2c98f916b6303
|
||||
golang.org/x/sync cd5d95a43a6e21273425c7ae415d3df9ea832eeb
|
||||
golang.org/x/sys eeed37f84f13f52d35e095e8023ba65671ff86a1
|
||||
golang.org/x/sys b64e53b001e413bd5067f36d4e439eded3827374
|
||||
golang.org/x/term f5c789dd3221ff39d752ac54467d762de7cfbec6
|
||||
golang.org/x/text 23ae387dee1f90d29a23c0e87ee0b46038fbed0e # v0.3.3
|
||||
golang.org/x/time 555d28b269f0569763d25dbe1a237ae74c6bcc82
|
||||
|
||||
27
vendor/github.com/agl/ed25519/LICENSE
generated
vendored
27
vendor/github.com/agl/ed25519/LICENSE
generated
vendored
@ -1,27 +0,0 @@
|
||||
Copyright (c) 2012 The Go Authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
127
vendor/github.com/agl/ed25519/ed25519.go
generated
vendored
127
vendor/github.com/agl/ed25519/ed25519.go
generated
vendored
@ -1,127 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package ed25519 implements the Ed25519 signature algorithm. See
|
||||
// http://ed25519.cr.yp.to/.
|
||||
package ed25519
|
||||
|
||||
// This code is a port of the public domain, "ref10" implementation of ed25519
|
||||
// from SUPERCOP.
|
||||
|
||||
import (
|
||||
"crypto/sha512"
|
||||
"crypto/subtle"
|
||||
"io"
|
||||
|
||||
"github.com/agl/ed25519/edwards25519"
|
||||
)
|
||||
|
||||
const (
|
||||
PublicKeySize = 32
|
||||
PrivateKeySize = 64
|
||||
SignatureSize = 64
|
||||
)
|
||||
|
||||
// GenerateKey generates a public/private key pair using randomness from rand.
|
||||
func GenerateKey(rand io.Reader) (publicKey *[PublicKeySize]byte, privateKey *[PrivateKeySize]byte, err error) {
|
||||
privateKey = new([64]byte)
|
||||
publicKey = new([32]byte)
|
||||
_, err = io.ReadFull(rand, privateKey[:32])
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
h := sha512.New()
|
||||
h.Write(privateKey[:32])
|
||||
digest := h.Sum(nil)
|
||||
|
||||
digest[0] &= 248
|
||||
digest[31] &= 127
|
||||
digest[31] |= 64
|
||||
|
||||
var A edwards25519.ExtendedGroupElement
|
||||
var hBytes [32]byte
|
||||
copy(hBytes[:], digest)
|
||||
edwards25519.GeScalarMultBase(&A, &hBytes)
|
||||
A.ToBytes(publicKey)
|
||||
|
||||
copy(privateKey[32:], publicKey[:])
|
||||
return
|
||||
}
|
||||
|
||||
// Sign signs the message with privateKey and returns a signature.
|
||||
func Sign(privateKey *[PrivateKeySize]byte, message []byte) *[SignatureSize]byte {
|
||||
h := sha512.New()
|
||||
h.Write(privateKey[:32])
|
||||
|
||||
var digest1, messageDigest, hramDigest [64]byte
|
||||
var expandedSecretKey [32]byte
|
||||
h.Sum(digest1[:0])
|
||||
copy(expandedSecretKey[:], digest1[:])
|
||||
expandedSecretKey[0] &= 248
|
||||
expandedSecretKey[31] &= 63
|
||||
expandedSecretKey[31] |= 64
|
||||
|
||||
h.Reset()
|
||||
h.Write(digest1[32:])
|
||||
h.Write(message)
|
||||
h.Sum(messageDigest[:0])
|
||||
|
||||
var messageDigestReduced [32]byte
|
||||
edwards25519.ScReduce(&messageDigestReduced, &messageDigest)
|
||||
var R edwards25519.ExtendedGroupElement
|
||||
edwards25519.GeScalarMultBase(&R, &messageDigestReduced)
|
||||
|
||||
var encodedR [32]byte
|
||||
R.ToBytes(&encodedR)
|
||||
|
||||
h.Reset()
|
||||
h.Write(encodedR[:])
|
||||
h.Write(privateKey[32:])
|
||||
h.Write(message)
|
||||
h.Sum(hramDigest[:0])
|
||||
var hramDigestReduced [32]byte
|
||||
edwards25519.ScReduce(&hramDigestReduced, &hramDigest)
|
||||
|
||||
var s [32]byte
|
||||
edwards25519.ScMulAdd(&s, &hramDigestReduced, &expandedSecretKey, &messageDigestReduced)
|
||||
|
||||
signature := new([64]byte)
|
||||
copy(signature[:], encodedR[:])
|
||||
copy(signature[32:], s[:])
|
||||
return signature
|
||||
}
|
||||
|
||||
// Verify returns true iff sig is a valid signature of message by publicKey.
|
||||
func Verify(publicKey *[PublicKeySize]byte, message []byte, sig *[SignatureSize]byte) bool {
|
||||
if sig[63]&224 != 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
var A edwards25519.ExtendedGroupElement
|
||||
if !A.FromBytes(publicKey) {
|
||||
return false
|
||||
}
|
||||
edwards25519.FeNeg(&A.X, &A.X)
|
||||
edwards25519.FeNeg(&A.T, &A.T)
|
||||
|
||||
h := sha512.New()
|
||||
h.Write(sig[:32])
|
||||
h.Write(publicKey[:])
|
||||
h.Write(message)
|
||||
var digest [64]byte
|
||||
h.Sum(digest[:0])
|
||||
|
||||
var hReduced [32]byte
|
||||
edwards25519.ScReduce(&hReduced, &digest)
|
||||
|
||||
var R edwards25519.ProjectiveGroupElement
|
||||
var b [32]byte
|
||||
copy(b[:], sig[32:])
|
||||
edwards25519.GeDoubleScalarMultVartime(&R, &hReduced, &A, &b)
|
||||
|
||||
var checkR [32]byte
|
||||
R.ToBytes(&checkR)
|
||||
return subtle.ConstantTimeCompare(sig[:32], checkR[:]) == 1
|
||||
}
|
||||
1411
vendor/github.com/agl/ed25519/edwards25519/const.go
generated
vendored
1411
vendor/github.com/agl/ed25519/edwards25519/const.go
generated
vendored
File diff suppressed because it is too large
Load Diff
1773
vendor/github.com/agl/ed25519/edwards25519/edwards25519.go
generated
vendored
1773
vendor/github.com/agl/ed25519/edwards25519/edwards25519.go
generated
vendored
File diff suppressed because it is too large
Load Diff
3
vendor/github.com/docker/docker-credential-helpers/client/command.go
generated
vendored
3
vendor/github.com/docker/docker-credential-helpers/client/command.go
generated
vendored
@ -4,7 +4,8 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
||||
exec "golang.org/x/sys/execabs"
|
||||
)
|
||||
|
||||
// Program is an interface to execute external programs.
|
||||
|
||||
8
vendor/github.com/docker/docker-credential-helpers/go.mod
generated
vendored
Normal file
8
vendor/github.com/docker/docker-credential-helpers/go.mod
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
module github.com/docker/docker-credential-helpers
|
||||
|
||||
go 1.13
|
||||
|
||||
require (
|
||||
github.com/danieljoos/wincred v1.1.0
|
||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4
|
||||
)
|
||||
13
vendor/github.com/docker/docker-credential-helpers/osxkeychain/osxkeychain_darwin.go
generated
vendored
13
vendor/github.com/docker/docker-credential-helpers/osxkeychain/osxkeychain_darwin.go
generated
vendored
@ -21,6 +21,13 @@ import (
|
||||
// when the credentials are not in the keychain.
|
||||
const errCredentialsNotFound = "The specified item could not be found in the keychain."
|
||||
|
||||
// errCredentialsNotFound is the specific error message returned by OS X
|
||||
// when environment does not allow showing dialog to unlock keychain.
|
||||
const errInteractionNotAllowed = "User interaction is not allowed."
|
||||
|
||||
// ErrInteractionNotAllowed is returned if keychain password prompt can not be shown.
|
||||
var ErrInteractionNotAllowed = errors.New(`keychain cannot be accessed because the current session does not allow user interaction. The keychain may be locked; unlock it by running "security -v unlock-keychain ~/Library/Keychains/login.keychain-db" and try again`)
|
||||
|
||||
// Osxkeychain handles secrets using the OS X Keychain as store.
|
||||
type Osxkeychain struct{}
|
||||
|
||||
@ -89,6 +96,9 @@ func (h Osxkeychain) Get(serverURL string) (string, string, error) {
|
||||
if goMsg == errCredentialsNotFound {
|
||||
return "", "", credentials.NewErrCredentialsNotFound()
|
||||
}
|
||||
if goMsg == errInteractionNotAllowed {
|
||||
return "", "", ErrInteractionNotAllowed
|
||||
}
|
||||
|
||||
return "", "", errors.New(goMsg)
|
||||
}
|
||||
@ -117,6 +127,9 @@ func (h Osxkeychain) List() (map[string]string, error) {
|
||||
if goMsg == errCredentialsNotFound {
|
||||
return make(map[string]string), nil
|
||||
}
|
||||
if goMsg == errInteractionNotAllowed {
|
||||
return nil, ErrInteractionNotAllowed
|
||||
}
|
||||
|
||||
return nil, errors.New(goMsg)
|
||||
}
|
||||
|
||||
2
vendor/github.com/docker/docker/builder/remotecontext/git/gitutils.go
generated
vendored
2
vendor/github.com/docker/docker/builder/remotecontext/git/gitutils.go
generated
vendored
@ -5,12 +5,12 @@ import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/moby/sys/symlink"
|
||||
"github.com/pkg/errors"
|
||||
exec "golang.org/x/sys/execabs"
|
||||
)
|
||||
|
||||
type gitRepo struct {
|
||||
|
||||
2
vendor/github.com/docker/docker/pkg/archive/archive.go
generated
vendored
2
vendor/github.com/docker/docker/pkg/archive/archive.go
generated
vendored
@ -11,7 +11,6 @@ import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
@ -25,6 +24,7 @@ import (
|
||||
"github.com/docker/docker/pkg/pools"
|
||||
"github.com/docker/docker/pkg/system"
|
||||
"github.com/sirupsen/logrus"
|
||||
exec "golang.org/x/sys/execabs"
|
||||
)
|
||||
|
||||
type (
|
||||
|
||||
11
vendor/github.com/docker/docker/pkg/idtools/idtools.go
generated
vendored
11
vendor/github.com/docker/docker/pkg/idtools/idtools.go
generated
vendored
@ -35,13 +35,13 @@ const (
|
||||
|
||||
// MkdirAllAndChown creates a directory (include any along the path) and then modifies
|
||||
// ownership to the requested uid/gid. If the directory already exists, this
|
||||
// function will still change ownership to the requested uid/gid pair.
|
||||
// function will still change ownership and permissions.
|
||||
func MkdirAllAndChown(path string, mode os.FileMode, owner Identity) error {
|
||||
return mkdirAs(path, mode, owner, true, true)
|
||||
}
|
||||
|
||||
// MkdirAndChown creates a directory and then modifies ownership to the requested uid/gid.
|
||||
// If the directory already exists, this function still changes ownership.
|
||||
// If the directory already exists, this function still changes ownership and permissions.
|
||||
// Note that unlike os.Mkdir(), this function does not return IsExist error
|
||||
// in case path already exists.
|
||||
func MkdirAndChown(path string, mode os.FileMode, owner Identity) error {
|
||||
@ -50,7 +50,7 @@ func MkdirAndChown(path string, mode os.FileMode, owner Identity) error {
|
||||
|
||||
// MkdirAllAndChownNew creates a directory (include any along the path) and then modifies
|
||||
// ownership ONLY of newly created directories to the requested uid/gid. If the
|
||||
// directories along the path exist, no change of ownership will be performed
|
||||
// directories along the path exist, no change of ownership or permissions will be performed
|
||||
func MkdirAllAndChownNew(path string, mode os.FileMode, owner Identity) error {
|
||||
return mkdirAs(path, mode, owner, true, false)
|
||||
}
|
||||
@ -234,3 +234,8 @@ func parseSubidFile(path, username string) (ranges, error) {
|
||||
|
||||
return rangeList, s.Err()
|
||||
}
|
||||
|
||||
// CurrentIdentity returns the identity of the current process
|
||||
func CurrentIdentity() Identity {
|
||||
return Identity{UID: os.Getuid(), GID: os.Getegid()}
|
||||
}
|
||||
|
||||
14
vendor/github.com/docker/docker/pkg/idtools/idtools_unix.go
generated
vendored
14
vendor/github.com/docker/docker/pkg/idtools/idtools_unix.go
generated
vendored
@ -40,7 +40,7 @@ func mkdirAs(path string, mode os.FileMode, owner Identity, mkAll, chownExisting
|
||||
}
|
||||
|
||||
// short-circuit--we were called with an existing directory and chown was requested
|
||||
return lazyChown(path, owner.UID, owner.GID, stat)
|
||||
return setPermissions(path, mode, owner.UID, owner.GID, stat)
|
||||
}
|
||||
|
||||
if os.IsNotExist(err) {
|
||||
@ -71,7 +71,7 @@ func mkdirAs(path string, mode os.FileMode, owner Identity, mkAll, chownExisting
|
||||
// even if it existed, we will chown the requested path + any subpaths that
|
||||
// didn't exist when we called MkdirAll
|
||||
for _, pathComponent := range paths {
|
||||
if err := lazyChown(pathComponent, owner.UID, owner.GID, nil); err != nil {
|
||||
if err := setPermissions(pathComponent, mode, owner.UID, owner.GID, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -213,10 +213,11 @@ func callGetent(database, key string) (io.Reader, error) {
|
||||
return bytes.NewReader(out), nil
|
||||
}
|
||||
|
||||
// lazyChown performs a chown only if the uid/gid don't match what's requested
|
||||
// setPermissions performs a chown/chmod only if the uid/gid don't match what's requested
|
||||
// Normally a Chown is a no-op if uid/gid match, but in some cases this can still cause an error, e.g. if the
|
||||
// dir is on an NFS share, so don't call chown unless we absolutely must.
|
||||
func lazyChown(p string, uid, gid int, stat *system.StatT) error {
|
||||
// Likewise for setting permissions.
|
||||
func setPermissions(p string, mode os.FileMode, uid, gid int, stat *system.StatT) error {
|
||||
if stat == nil {
|
||||
var err error
|
||||
stat, err = system.Stat(p)
|
||||
@ -224,6 +225,11 @@ func lazyChown(p string, uid, gid int, stat *system.StatT) error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if os.FileMode(stat.Mode()).Perm() != mode.Perm() {
|
||||
if err := os.Chmod(p, mode.Perm()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if stat.UID() == uint32(uid) && stat.GID() == uint32(gid) {
|
||||
return nil
|
||||
}
|
||||
|
||||
10
vendor/github.com/docker/docker/vendor.conf
generated
vendored
10
vendor/github.com/docker/docker/vendor.conf
generated
vendored
@ -20,11 +20,11 @@ github.com/creack/pty 2a38352e8b4d7ab6c336eef107e4
|
||||
github.com/sirupsen/logrus 6699a89a232f3db797f2e280639854bbc4b89725 # v1.7.0
|
||||
github.com/tchap/go-patricia a7f0089c6f496e8e70402f61733606daa326cac5 # v2.3.0
|
||||
golang.org/x/net ab34263943818b32f575efc978a3d24e80b04bd7
|
||||
golang.org/x/sys eeed37f84f13f52d35e095e8023ba65671ff86a1
|
||||
golang.org/x/sys b64e53b001e413bd5067f36d4e439eded3827374
|
||||
github.com/docker/go-units 519db1ee28dcc9fd2474ae59fca29a810482bfb1 # v0.4.0
|
||||
github.com/docker/go-connections 7395e3f8aa162843a74ed6d48e79627d9792ac55 # v0.4.0
|
||||
golang.org/x/text 23ae387dee1f90d29a23c0e87ee0b46038fbed0e # v0.3.3
|
||||
gotest.tools/v3 bb0d8a963040ea5048dcef1a14d8f8b58a33d4b3 # v3.0.2
|
||||
gotest.tools/v3 568bc57cc5c19a2ef85e5749870b49a4cc2ab54d # v3.0.3
|
||||
github.com/google/go-cmp 3af367b6b30c263d47e8895973edcca9a49cf029 # v0.2.0
|
||||
github.com/syndtr/gocapability 42c35b4376354fd554efc7ad35e0b7f94e3a0ffb
|
||||
|
||||
@ -33,7 +33,7 @@ github.com/imdario/mergo 1afb36080aec31e0d1528973ebe6
|
||||
golang.org/x/sync cd5d95a43a6e21273425c7ae415d3df9ea832eeb
|
||||
|
||||
# buildkit
|
||||
github.com/moby/buildkit 8142d66b5ebde79846b869fba30d9d30633e74aa # v0.8.1
|
||||
github.com/moby/buildkit 68bb095353c65bc3993fd534c26cf77fe05e61b1 # v0.8 branch
|
||||
github.com/tonistiigi/fsutil 0834f99b7b85462efb69b4f571a4fa3ca7da5ac9
|
||||
github.com/tonistiigi/units 6950e57a87eaf136bbe44ef2ec8e75b9e3569de2
|
||||
github.com/grpc-ecosystem/grpc-opentracing 8e809c8a86450a29b90dcc9efbf062d0fe6d9746
|
||||
@ -47,7 +47,7 @@ github.com/grpc-ecosystem/go-grpc-middleware 3c51f7f332123e8be5a157c0802a
|
||||
# libnetwork
|
||||
|
||||
# When updating, also update LIBNETWORK_COMMIT in hack/dockerfile/install/proxy.installer accordingly
|
||||
github.com/docker/libnetwork 5c6a95bfb20c61571a00f913c6b91959ede84e8d
|
||||
github.com/docker/libnetwork fa125a3512ee0f6187721c88582bf8c4378bd4d7
|
||||
github.com/docker/go-events e31b211e4f1cd09aa76fe4ac244571fab96ae47f
|
||||
github.com/armon/go-radix e39d623f12e8e41c7b5529e9a9dd67a1e2261f80
|
||||
github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec
|
||||
@ -176,7 +176,7 @@ github.com/morikuni/aec 39771216ff4c63d11f5e604076f9
|
||||
# metrics
|
||||
github.com/docker/go-metrics b619b3592b65de4f087d9f16863a7e6ff905973c # v0.0.1
|
||||
|
||||
github.com/opencontainers/selinux 25504e34a9826d481f6e2903963ecaa881749124 # v1.6.0
|
||||
github.com/opencontainers/selinux 2f45b3796d18f1ab4c9fc0c888a98d0a0fd6e429 # v1.8.0
|
||||
github.com/willf/bitset 559910e8471e48d76d9e5a1ba15842dee77ad45d # v1.1.11
|
||||
|
||||
|
||||
|
||||
40
vendor/github.com/theupdateframework/notary/README.md
generated
vendored
40
vendor/github.com/theupdateframework/notary/README.md
generated
vendored
@ -21,7 +21,7 @@ for more information.
|
||||
|
||||
Notary aims to make the internet more secure by making it easy for people to
|
||||
publish and verify content. We often rely on TLS to secure our communications
|
||||
with a web server which is inherently flawed, as any compromise of the server
|
||||
with a web server, which is inherently flawed, as any compromise of the server
|
||||
enables malicious content to be substituted for the legitimate content.
|
||||
|
||||
With Notary, publishers can sign their content offline using keys kept highly
|
||||
@ -46,11 +46,16 @@ Notary is based on [The Update Framework](https://www.theupdateframework.com/),
|
||||
|
||||
## Security
|
||||
|
||||
Any security vulnerabilities can be reported to security@docker.com.
|
||||
|
||||
See Notary's [service architecture docs](docs/service_architecture.md#threat-model) for more information about our threat model, which details the varying survivability and severities for key compromise as well as mitigations.
|
||||
|
||||
Notary's last security audit was on July 31, 2015 by NCC ([results](docs/resources/ncc_docker_notary_audit_2015_07_31.pdf)).
|
||||
### Security Audits
|
||||
|
||||
Any security vulnerabilities can be reported to security@docker.com.
|
||||
Notary has had two public security audits:
|
||||
|
||||
* [August 7, 2018 by Cure53](docs/resources/cure53_tuf_notary_audit_2018_08_07.pdf) covering TUF and Notary
|
||||
* [July 31, 2015 by NCC](docs/resources/ncc_docker_notary_audit_2015_07_31.pdf) covering Notary
|
||||
|
||||
# Getting started with the Notary CLI
|
||||
|
||||
@ -65,7 +70,7 @@ For more advanced usage, see the
|
||||
|
||||
To use the CLI against a local Notary server rather than against Docker Hub:
|
||||
|
||||
1. Ensure that you have [docker and docker-compose](http://docs.docker.com/compose/install/) installed.
|
||||
1. Ensure that you have [docker and docker-compose](https://docs.docker.com/compose/install/) installed.
|
||||
1. `git clone https://github.com/theupdateframework/notary.git` and from the cloned repository path,
|
||||
start up a local Notary server and signer and copy the config file and testing certs to your
|
||||
local Notary config directory:
|
||||
@ -88,6 +93,20 @@ URL is specified already in the configuration, file you copied.
|
||||
You can also leave off the `-d ~/.docker/trust` argument if you do not care
|
||||
to use `notary` with Docker images.
|
||||
|
||||
## Upgrading dependencies
|
||||
|
||||
To prevent mistakes in vendoring the go modules a buildscript has been added to properly vendor the modules using the correct version of Go to mitigate differences in CI and development environment.
|
||||
|
||||
Following procedure should be executed to upgrade a dependency. Preferably keep dependency upgrades in a separate commit from your code changes.
|
||||
|
||||
```bash
|
||||
go get -u github.com/spf13/viper
|
||||
buildscripts/circle-validate-vendor.sh
|
||||
git add .
|
||||
git commit -m "Upgraded github.com/spf13/viper"
|
||||
```
|
||||
|
||||
The `buildscripts/circle-validate-vendor.sh` runs `go mod tidy` and `go mod vendor` using the given version of Go to prevent differences if you are for example running on a different version of Go.
|
||||
|
||||
## Building Notary
|
||||
|
||||
@ -97,25 +116,20 @@ branch and contains features for the next release.
|
||||
|
||||
Prerequisites:
|
||||
|
||||
- Go >= 1.7.1
|
||||
- Fedora: `dnf install golang`
|
||||
- libtool development headers installed
|
||||
- Ubuntu: `apt-get install libltdl-dev`
|
||||
- CentOS/RedHat: `yum install libtool-ltdl-devel`
|
||||
- Fedora: `dnf install libtool-ltdl-devel`
|
||||
- Mac OS ([Homebrew](http://brew.sh/)): `brew install libtool`
|
||||
* Go >= 1.12
|
||||
|
||||
Set [```GOPATH```](https://golang.org/doc/code.html#GOPATH). Then, run:
|
||||
|
||||
```bash
|
||||
$ export GO111MODULE=on
|
||||
$ go get github.com/theupdateframework/notary
|
||||
# build with pcks11 support by default to support yubikey
|
||||
# build with pkcs11 support by default to support yubikey
|
||||
$ go install -tags pkcs11 github.com/theupdateframework/notary/cmd/notary
|
||||
$ notary
|
||||
```
|
||||
|
||||
To build the server and signer, run `docker-compose build`.
|
||||
|
||||
|
||||
## License
|
||||
|
||||
[](https://app.fossa.io/projects/git%2Bgithub.com%2Ftheupdateframework%2Fnotary?ref=badge_large)
|
||||
|
||||
12
vendor/github.com/theupdateframework/notary/client/changelist/file_changelist.go
generated
vendored
12
vendor/github.com/theupdateframework/notary/client/changelist/file_changelist.go
generated
vendored
@ -35,7 +35,10 @@ func getFileNames(dirName string) ([]os.FileInfo, error) {
|
||||
if err != nil {
|
||||
return fileInfos, err
|
||||
}
|
||||
defer dir.Close()
|
||||
defer func() {
|
||||
_ = dir.Close()
|
||||
}()
|
||||
|
||||
dirListing, err = dir.Readdir(0)
|
||||
if err != nil {
|
||||
return fileInfos, err
|
||||
@ -89,7 +92,7 @@ func (cl FileChangelist) Add(c Change) error {
|
||||
return err
|
||||
}
|
||||
filename := fmt.Sprintf("%020d_%s.change", time.Now().UnixNano(), uuid.Generate())
|
||||
return ioutil.WriteFile(filepath.Join(cl.dir, filename), cJSON, 0644)
|
||||
return ioutil.WriteFile(filepath.Join(cl.dir, filename), cJSON, 0600)
|
||||
}
|
||||
|
||||
// Remove deletes the changes found at the given indices
|
||||
@ -120,7 +123,10 @@ func (cl FileChangelist) Clear(archive string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer dir.Close()
|
||||
defer func() {
|
||||
_ = dir.Close()
|
||||
}()
|
||||
|
||||
files, err := dir.Readdir(0)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
2
vendor/github.com/theupdateframework/notary/client/changelist/interface.go
generated
vendored
2
vendor/github.com/theupdateframework/notary/client/changelist/interface.go
generated
vendored
@ -20,7 +20,7 @@ type Changelist interface {
|
||||
// Remove deletes the changes corresponding with the indices given
|
||||
Remove(idxs []int) error
|
||||
|
||||
// Close syncronizes any pending writes to the underlying
|
||||
// Close synchronizes any pending writes to the underlying
|
||||
// storage and closes the file/connection
|
||||
Close() error
|
||||
|
||||
|
||||
428
vendor/github.com/theupdateframework/notary/client/client.go
generated
vendored
428
vendor/github.com/theupdateframework/notary/client/client.go
generated
vendored
@ -7,10 +7,8 @@ import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"time"
|
||||
|
||||
canonicaljson "github.com/docker/go/canonical/json"
|
||||
@ -39,7 +37,6 @@ func init() {
|
||||
|
||||
// repository stores all the information needed to operate on a notary repository.
|
||||
type repository struct {
|
||||
baseDir string
|
||||
gun data.GUN
|
||||
baseURL string
|
||||
changelist changelist.Changelist
|
||||
@ -56,7 +53,8 @@ type repository struct {
|
||||
// NewFileCachedRepository is a wrapper for NewRepository that initializes
|
||||
// a file cache from the provided repository, local config information and a crypto service.
|
||||
// It also retrieves the remote store associated to the base directory under where all the
|
||||
// trust files will be stored and the specified GUN.
|
||||
// trust files will be stored (This is normally defaults to "~/.notary" or "~/.docker/trust"
|
||||
// when enabling Docker content trust) and the specified GUN.
|
||||
//
|
||||
// In case of a nil RoundTripper, a default offline store is used instead.
|
||||
func NewFileCachedRepository(baseDir string, gun data.GUN, baseURL string, rt http.RoundTripper,
|
||||
@ -90,16 +88,13 @@ func NewFileCachedRepository(baseDir string, gun data.GUN, baseURL string, rt ht
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewRepository(baseDir, gun, baseURL, remoteStore, cache, trustPinning, cryptoService, cl)
|
||||
return NewRepository(gun, baseURL, remoteStore, cache, trustPinning, cryptoService, cl)
|
||||
}
|
||||
|
||||
// NewRepository is the base method that returns a new notary repository.
|
||||
// It takes the base directory under where all the trust files will be stored
|
||||
// (This is normally defaults to "~/.notary" or "~/.docker/trust" when enabling
|
||||
// docker content trust).
|
||||
// It expects an initialized cache. In case of a nil remote store, a default
|
||||
// offline store is used.
|
||||
func NewRepository(baseDir string, gun data.GUN, baseURL string, remoteStore store.RemoteStore, cache store.MetadataStore,
|
||||
func NewRepository(gun data.GUN, baseURL string, remoteStore store.RemoteStore, cache store.MetadataStore,
|
||||
trustPinning trustpinning.TrustPinConfig, cryptoService signed.CryptoService, cl changelist.Changelist) (Repository, error) {
|
||||
|
||||
// Repo's remote store is either a valid remote store or an OfflineStore
|
||||
@ -114,7 +109,6 @@ func NewRepository(baseDir string, gun data.GUN, baseURL string, remoteStore sto
|
||||
nRepo := &repository{
|
||||
gun: gun,
|
||||
baseURL: baseURL,
|
||||
baseDir: baseDir,
|
||||
changelist: cl,
|
||||
cache: cache,
|
||||
remoteStore: remoteStore,
|
||||
@ -131,20 +125,62 @@ func (r *repository) GetGUN() data.GUN {
|
||||
return r.gun
|
||||
}
|
||||
|
||||
// Target represents a simplified version of the data TUF operates on, so external
|
||||
// applications don't have to depend on TUF data types.
|
||||
type Target struct {
|
||||
Name string // the name of the target
|
||||
Hashes data.Hashes // the hash of the target
|
||||
Length int64 // the size in bytes of the target
|
||||
Custom *canonicaljson.RawMessage // the custom data provided to describe the file at TARGETPATH
|
||||
func (r *repository) updateTUF(forWrite bool) error {
|
||||
repo, invalid, err := LoadTUFRepo(TUFLoadOptions{
|
||||
GUN: r.gun,
|
||||
TrustPinning: r.trustPinning,
|
||||
CryptoService: r.cryptoService,
|
||||
Cache: r.cache,
|
||||
RemoteStore: r.remoteStore,
|
||||
AlwaysCheckInitialized: forWrite,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r.tufRepo = repo
|
||||
r.invalid = invalid
|
||||
return nil
|
||||
}
|
||||
|
||||
// TargetWithRole represents a Target that exists in a particular role - this is
|
||||
// produced by ListTargets and GetTargetByName
|
||||
type TargetWithRole struct {
|
||||
Target
|
||||
Role data.RoleName
|
||||
// ListTargets calls update first before listing targets
|
||||
func (r *repository) ListTargets(roles ...data.RoleName) ([]*TargetWithRole, error) {
|
||||
if err := r.updateTUF(false); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewReadOnly(r.tufRepo).ListTargets(roles...)
|
||||
}
|
||||
|
||||
// GetTargetByName calls update first before getting target by name
|
||||
func (r *repository) GetTargetByName(name string, roles ...data.RoleName) (*TargetWithRole, error) {
|
||||
if err := r.updateTUF(false); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewReadOnly(r.tufRepo).GetTargetByName(name, roles...)
|
||||
}
|
||||
|
||||
// GetAllTargetMetadataByName calls update first before getting targets by name
|
||||
func (r *repository) GetAllTargetMetadataByName(name string) ([]TargetSignedStruct, error) {
|
||||
if err := r.updateTUF(false); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewReadOnly(r.tufRepo).GetAllTargetMetadataByName(name)
|
||||
|
||||
}
|
||||
|
||||
// ListRoles calls update first before getting roles
|
||||
func (r *repository) ListRoles() ([]RoleWithSignatures, error) {
|
||||
if err := r.updateTUF(false); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewReadOnly(r.tufRepo).ListRoles()
|
||||
}
|
||||
|
||||
// GetDelegationRoles calls update first before getting all delegation roles
|
||||
func (r *repository) GetDelegationRoles() ([]data.Role, error) {
|
||||
if err := r.updateTUF(false); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewReadOnly(r.tufRepo).GetDelegationRoles()
|
||||
}
|
||||
|
||||
// NewTarget is a helper method that returns a Target
|
||||
@ -493,167 +529,6 @@ func (r *repository) RemoveTarget(targetName string, roles ...data.RoleName) err
|
||||
return addChange(r.changelist, template, roles...)
|
||||
}
|
||||
|
||||
// ListTargets lists all targets for the current repository. The list of
|
||||
// roles should be passed in order from highest to lowest priority.
|
||||
//
|
||||
// IMPORTANT: if you pass a set of roles such as [ "targets/a", "targets/x"
|
||||
// "targets/a/b" ], even though "targets/a/b" is part of the "targets/a" subtree
|
||||
// its entries will be strictly shadowed by those in other parts of the "targets/a"
|
||||
// subtree and also the "targets/x" subtree, as we will defer parsing it until
|
||||
// we explicitly reach it in our iteration of the provided list of roles.
|
||||
func (r *repository) ListTargets(roles ...data.RoleName) ([]*TargetWithRole, error) {
|
||||
if err := r.Update(false); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(roles) == 0 {
|
||||
roles = []data.RoleName{data.CanonicalTargetsRole}
|
||||
}
|
||||
targets := make(map[string]*TargetWithRole)
|
||||
for _, role := range roles {
|
||||
// Define an array of roles to skip for this walk (see IMPORTANT comment above)
|
||||
skipRoles := utils.RoleNameSliceRemove(roles, role)
|
||||
|
||||
// Define a visitor function to populate the targets map in priority order
|
||||
listVisitorFunc := func(tgt *data.SignedTargets, validRole data.DelegationRole) interface{} {
|
||||
// We found targets so we should try to add them to our targets map
|
||||
for targetName, targetMeta := range tgt.Signed.Targets {
|
||||
// Follow the priority by not overriding previously set targets
|
||||
// and check that this path is valid with this role
|
||||
if _, ok := targets[targetName]; ok || !validRole.CheckPaths(targetName) {
|
||||
continue
|
||||
}
|
||||
targets[targetName] = &TargetWithRole{
|
||||
Target: Target{
|
||||
Name: targetName,
|
||||
Hashes: targetMeta.Hashes,
|
||||
Length: targetMeta.Length,
|
||||
Custom: targetMeta.Custom,
|
||||
},
|
||||
Role: validRole.Name,
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
r.tufRepo.WalkTargets("", role, listVisitorFunc, skipRoles...)
|
||||
}
|
||||
|
||||
var targetList []*TargetWithRole
|
||||
for _, v := range targets {
|
||||
targetList = append(targetList, v)
|
||||
}
|
||||
|
||||
return targetList, nil
|
||||
}
|
||||
|
||||
// GetTargetByName returns a target by the given name. If no roles are passed
|
||||
// it uses the targets role and does a search of the entire delegation
|
||||
// graph, finding the first entry in a breadth first search of the delegations.
|
||||
// If roles are passed, they should be passed in descending priority and
|
||||
// the target entry found in the subtree of the highest priority role
|
||||
// will be returned.
|
||||
// See the IMPORTANT section on ListTargets above. Those roles also apply here.
|
||||
func (r *repository) GetTargetByName(name string, roles ...data.RoleName) (*TargetWithRole, error) {
|
||||
if err := r.Update(false); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(roles) == 0 {
|
||||
roles = append(roles, data.CanonicalTargetsRole)
|
||||
}
|
||||
var resultMeta data.FileMeta
|
||||
var resultRoleName data.RoleName
|
||||
var foundTarget bool
|
||||
for _, role := range roles {
|
||||
// Define an array of roles to skip for this walk (see IMPORTANT comment above)
|
||||
skipRoles := utils.RoleNameSliceRemove(roles, role)
|
||||
|
||||
// Define a visitor function to find the specified target
|
||||
getTargetVisitorFunc := func(tgt *data.SignedTargets, validRole data.DelegationRole) interface{} {
|
||||
if tgt == nil {
|
||||
return nil
|
||||
}
|
||||
// We found the target and validated path compatibility in our walk,
|
||||
// so we should stop our walk and set the resultMeta and resultRoleName variables
|
||||
if resultMeta, foundTarget = tgt.Signed.Targets[name]; foundTarget {
|
||||
resultRoleName = validRole.Name
|
||||
return tuf.StopWalk{}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
// Check that we didn't error, and that we assigned to our target
|
||||
if err := r.tufRepo.WalkTargets(name, role, getTargetVisitorFunc, skipRoles...); err == nil && foundTarget {
|
||||
return &TargetWithRole{Target: Target{Name: name, Hashes: resultMeta.Hashes, Length: resultMeta.Length, Custom: resultMeta.Custom}, Role: resultRoleName}, nil
|
||||
}
|
||||
}
|
||||
return nil, ErrNoSuchTarget(name)
|
||||
|
||||
}
|
||||
|
||||
// TargetSignedStruct is a struct that contains a Target, the role it was found in, and the list of signatures for that role
|
||||
type TargetSignedStruct struct {
|
||||
Role data.DelegationRole
|
||||
Target Target
|
||||
Signatures []data.Signature
|
||||
}
|
||||
|
||||
//ErrNoSuchTarget is returned when no valid trust data is found.
|
||||
type ErrNoSuchTarget string
|
||||
|
||||
func (f ErrNoSuchTarget) Error() string {
|
||||
return fmt.Sprintf("No valid trust data for %s", string(f))
|
||||
}
|
||||
|
||||
// GetAllTargetMetadataByName searches the entire delegation role tree to find the specified target by name for all
|
||||
// roles, and returns a list of TargetSignedStructs for each time it finds the specified target.
|
||||
// If given an empty string for a target name, it will return back all targets signed into the repository in every role
|
||||
func (r *repository) GetAllTargetMetadataByName(name string) ([]TargetSignedStruct, error) {
|
||||
if err := r.Update(false); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var targetInfoList []TargetSignedStruct
|
||||
|
||||
// Define a visitor function to find the specified target
|
||||
getAllTargetInfoByNameVisitorFunc := func(tgt *data.SignedTargets, validRole data.DelegationRole) interface{} {
|
||||
if tgt == nil {
|
||||
return nil
|
||||
}
|
||||
// We found a target and validated path compatibility in our walk,
|
||||
// so add it to our list if we have a match
|
||||
// if we have an empty name, add all targets, else check if we have it
|
||||
var targetMetaToAdd data.Files
|
||||
if name == "" {
|
||||
targetMetaToAdd = tgt.Signed.Targets
|
||||
} else {
|
||||
if meta, ok := tgt.Signed.Targets[name]; ok {
|
||||
targetMetaToAdd = data.Files{name: meta}
|
||||
}
|
||||
}
|
||||
|
||||
for targetName, resultMeta := range targetMetaToAdd {
|
||||
targetInfo := TargetSignedStruct{
|
||||
Role: validRole,
|
||||
Target: Target{Name: targetName, Hashes: resultMeta.Hashes, Length: resultMeta.Length, Custom: resultMeta.Custom},
|
||||
Signatures: tgt.Signatures,
|
||||
}
|
||||
targetInfoList = append(targetInfoList, targetInfo)
|
||||
}
|
||||
// continue walking to all child roles
|
||||
return nil
|
||||
}
|
||||
|
||||
// Check that we didn't error, and that we found the target at least once
|
||||
if err := r.tufRepo.WalkTargets(name, "", getAllTargetInfoByNameVisitorFunc); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(targetInfoList) == 0 {
|
||||
return nil, ErrNoSuchTarget(name)
|
||||
}
|
||||
return targetInfoList, nil
|
||||
}
|
||||
|
||||
// GetChangelist returns the list of the repository's unpublished changes
|
||||
func (r *repository) GetChangelist() (changelist.Changelist, error) {
|
||||
return r.changelist, nil
|
||||
@ -671,51 +546,6 @@ func (r *repository) getRemoteStore() store.RemoteStore {
|
||||
return r.remoteStore
|
||||
}
|
||||
|
||||
// RoleWithSignatures is a Role with its associated signatures
|
||||
type RoleWithSignatures struct {
|
||||
Signatures []data.Signature
|
||||
data.Role
|
||||
}
|
||||
|
||||
// ListRoles returns a list of RoleWithSignatures objects for this repo
|
||||
// This represents the latest metadata for each role in this repo
|
||||
func (r *repository) ListRoles() ([]RoleWithSignatures, error) {
|
||||
// Update to latest repo state
|
||||
if err := r.Update(false); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Get all role info from our updated keysDB, can be empty
|
||||
roles := r.tufRepo.GetAllLoadedRoles()
|
||||
|
||||
var roleWithSigs []RoleWithSignatures
|
||||
|
||||
// Populate RoleWithSignatures with Role from keysDB and signatures from TUF metadata
|
||||
for _, role := range roles {
|
||||
roleWithSig := RoleWithSignatures{Role: *role, Signatures: nil}
|
||||
switch role.Name {
|
||||
case data.CanonicalRootRole:
|
||||
roleWithSig.Signatures = r.tufRepo.Root.Signatures
|
||||
case data.CanonicalTargetsRole:
|
||||
roleWithSig.Signatures = r.tufRepo.Targets[data.CanonicalTargetsRole].Signatures
|
||||
case data.CanonicalSnapshotRole:
|
||||
roleWithSig.Signatures = r.tufRepo.Snapshot.Signatures
|
||||
case data.CanonicalTimestampRole:
|
||||
roleWithSig.Signatures = r.tufRepo.Timestamp.Signatures
|
||||
default:
|
||||
if !data.IsDelegation(role.Name) {
|
||||
continue
|
||||
}
|
||||
if _, ok := r.tufRepo.Targets[role.Name]; ok {
|
||||
// We'll only find a signature if we've published any targets with this delegation
|
||||
roleWithSig.Signatures = r.tufRepo.Targets[role.Name].Signatures
|
||||
}
|
||||
}
|
||||
roleWithSigs = append(roleWithSigs, roleWithSig)
|
||||
}
|
||||
return roleWithSigs, nil
|
||||
}
|
||||
|
||||
// Publish pushes the local changes in signed material to the remote notary-server
|
||||
// Conceptually it performs an operation similar to a `git rebase`
|
||||
func (r *repository) Publish() error {
|
||||
@ -736,7 +566,7 @@ func (r *repository) Publish() error {
|
||||
func (r *repository) publish(cl changelist.Changelist) error {
|
||||
var initialPublish bool
|
||||
// update first before publishing
|
||||
if err := r.Update(true); err != nil {
|
||||
if err := r.updateTUF(true); err != nil {
|
||||
// If the remote is not aware of the repo, then this is being published
|
||||
// for the first time. Try to initialize the repository before publishing.
|
||||
if _, ok := err.(ErrRepositoryNotExist); ok {
|
||||
@ -863,7 +693,14 @@ func (r *repository) oldKeysForLegacyClientSupport(legacyVersions int, initialPu
|
||||
}
|
||||
oldKeys := make(map[string]data.PublicKey)
|
||||
|
||||
c, err := r.bootstrapClient(true)
|
||||
c, err := bootstrapClient(TUFLoadOptions{
|
||||
GUN: r.gun,
|
||||
TrustPinning: r.trustPinning,
|
||||
CryptoService: r.cryptoService,
|
||||
Cache: r.cache,
|
||||
RemoteStore: r.remoteStore,
|
||||
AlwaysCheckInitialized: true,
|
||||
})
|
||||
// require a server connection to fetch old roots
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -1003,135 +840,6 @@ func (r *repository) saveMetadata(ignoreSnapshot bool) error {
|
||||
return r.cache.Set(data.CanonicalSnapshotRole.String(), snapshotJSON)
|
||||
}
|
||||
|
||||
// returns a properly constructed ErrRepositoryNotExist error based on this
|
||||
// repo's information
|
||||
func (r *repository) errRepositoryNotExist() error {
|
||||
host := r.baseURL
|
||||
parsed, err := url.Parse(r.baseURL)
|
||||
if err == nil {
|
||||
host = parsed.Host // try to exclude the scheme and any paths
|
||||
}
|
||||
return ErrRepositoryNotExist{remote: host, gun: r.gun}
|
||||
}
|
||||
|
||||
// Update bootstraps a trust anchor (root.json) before updating all the
|
||||
// metadata from the repo.
|
||||
func (r *repository) Update(forWrite bool) error {
|
||||
c, err := r.bootstrapClient(forWrite)
|
||||
if err != nil {
|
||||
if _, ok := err.(store.ErrMetaNotFound); ok {
|
||||
return r.errRepositoryNotExist()
|
||||
}
|
||||
return err
|
||||
}
|
||||
repo, invalid, err := c.Update()
|
||||
if err != nil {
|
||||
// notFound.Resource may include a version or checksum so when the role is root,
|
||||
// it will be root, <version>.root or root.<checksum>.
|
||||
notFound, ok := err.(store.ErrMetaNotFound)
|
||||
isRoot, _ := regexp.MatchString(`\.?`+data.CanonicalRootRole.String()+`\.?`, notFound.Resource)
|
||||
if ok && isRoot {
|
||||
return r.errRepositoryNotExist()
|
||||
}
|
||||
return err
|
||||
}
|
||||
// we can be assured if we are at this stage that the repo we built is good
|
||||
// no need to test the following function call for an error as it will always be fine should the repo be good- it is!
|
||||
r.tufRepo = repo
|
||||
r.invalid = invalid
|
||||
warnRolesNearExpiry(repo)
|
||||
return nil
|
||||
}
|
||||
|
||||
// bootstrapClient attempts to bootstrap a root.json to be used as the trust
|
||||
// anchor for a repository. The checkInitialized argument indicates whether
|
||||
// we should always attempt to contact the server to determine if the repository
|
||||
// is initialized or not. If set to true, we will always attempt to download
|
||||
// and return an error if the remote repository errors.
|
||||
//
|
||||
// Populates a tuf.RepoBuilder with this root metadata. If the root metadata
|
||||
// downloaded is a newer version than what is on disk, then intermediate
|
||||
// versions will be downloaded and verified in order to rotate trusted keys
|
||||
// properly. Newer root metadata must always be signed with the previous
|
||||
// threshold and keys.
|
||||
//
|
||||
// Fails if the remote server is reachable and does not know the repo
|
||||
// (i.e. before the first r.Publish()), in which case the error is
|
||||
// store.ErrMetaNotFound, or if the root metadata (from whichever source is used)
|
||||
// is not trusted.
|
||||
//
|
||||
// Returns a TUFClient for the remote server, which may not be actually
|
||||
// operational (if the URL is invalid but a root.json is cached).
|
||||
func (r *repository) bootstrapClient(checkInitialized bool) (*tufClient, error) {
|
||||
minVersion := 1
|
||||
// the old root on disk should not be validated against any trust pinning configuration
|
||||
// because if we have an old root, it itself is the thing that pins trust
|
||||
oldBuilder := tuf.NewRepoBuilder(r.gun, r.GetCryptoService(), trustpinning.TrustPinConfig{})
|
||||
|
||||
// by default, we want to use the trust pinning configuration on any new root that we download
|
||||
newBuilder := tuf.NewRepoBuilder(r.gun, r.GetCryptoService(), r.trustPinning)
|
||||
|
||||
// Try to read root from cache first. We will trust this root until we detect a problem
|
||||
// during update which will cause us to download a new root and perform a rotation.
|
||||
// If we have an old root, and it's valid, then we overwrite the newBuilder to be one
|
||||
// preloaded with the old root or one which uses the old root for trust bootstrapping.
|
||||
if rootJSON, err := r.cache.GetSized(data.CanonicalRootRole.String(), store.NoSizeLimit); err == nil {
|
||||
// if we can't load the cached root, fail hard because that is how we pin trust
|
||||
if err := oldBuilder.Load(data.CanonicalRootRole, rootJSON, minVersion, true); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// again, the root on disk is the source of trust pinning, so use an empty trust
|
||||
// pinning configuration
|
||||
newBuilder = tuf.NewRepoBuilder(r.gun, r.GetCryptoService(), trustpinning.TrustPinConfig{})
|
||||
|
||||
if err := newBuilder.Load(data.CanonicalRootRole, rootJSON, minVersion, false); err != nil {
|
||||
// Ok, the old root is expired - we want to download a new one. But we want to use the
|
||||
// old root to verify the new root, so bootstrap a new builder with the old builder
|
||||
// but use the trustpinning to validate the new root
|
||||
minVersion = oldBuilder.GetLoadedVersion(data.CanonicalRootRole)
|
||||
newBuilder = oldBuilder.BootstrapNewBuilderWithNewTrustpin(r.trustPinning)
|
||||
}
|
||||
}
|
||||
|
||||
remote := r.getRemoteStore()
|
||||
|
||||
if !newBuilder.IsLoaded(data.CanonicalRootRole) || checkInitialized {
|
||||
// remoteErr was nil and we were not able to load a root from cache or
|
||||
// are specifically checking for initialization of the repo.
|
||||
|
||||
// if remote store successfully set up, try and get root from remote
|
||||
// We don't have any local data to determine the size of root, so try the maximum (though it is restricted at 100MB)
|
||||
tmpJSON, err := remote.GetSized(data.CanonicalRootRole.String(), store.NoSizeLimit)
|
||||
if err != nil {
|
||||
// we didn't have a root in cache and were unable to load one from
|
||||
// the server. Nothing we can do but error.
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !newBuilder.IsLoaded(data.CanonicalRootRole) {
|
||||
// we always want to use the downloaded root if we couldn't load from cache
|
||||
if err := newBuilder.Load(data.CanonicalRootRole, tmpJSON, minVersion, false); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = r.cache.Set(data.CanonicalRootRole.String(), tmpJSON)
|
||||
if err != nil {
|
||||
// if we can't write cache we should still continue, just log error
|
||||
logrus.Errorf("could not save root to cache: %s", err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We can only get here if remoteErr != nil (hence we don't download any new root),
|
||||
// and there was no root on disk
|
||||
if !newBuilder.IsLoaded(data.CanonicalRootRole) {
|
||||
return nil, ErrRepoNotInitialized{}
|
||||
}
|
||||
|
||||
return newTufClient(oldBuilder, newBuilder, remote, r.cache), nil
|
||||
}
|
||||
|
||||
// RotateKey removes all existing keys associated with the role. If no keys are
|
||||
// specified in keyList, then this creates and adds one new key or delegates
|
||||
// managing the key to the server. If key(s) are specified by keyList, then they are
|
||||
@ -1273,7 +981,7 @@ func DeleteTrustData(baseDir string, gun data.GUN, URL string, rt http.RoundTrip
|
||||
if deleteRemote {
|
||||
remote, err := getRemoteStore(URL, gun, rt)
|
||||
if err != nil {
|
||||
logrus.Error("unable to instantiate a remote store: %v", err)
|
||||
logrus.Errorf("unable to instantiate a remote store: %v", err)
|
||||
return err
|
||||
}
|
||||
if err := remote.RemoveAll(); err != nil {
|
||||
|
||||
38
vendor/github.com/theupdateframework/notary/client/delegations.go
generated
vendored
38
vendor/github.com/theupdateframework/notary/client/delegations.go
generated
vendored
@ -7,7 +7,6 @@ import (
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/theupdateframework/notary"
|
||||
"github.com/theupdateframework/notary/client/changelist"
|
||||
store "github.com/theupdateframework/notary/storage"
|
||||
"github.com/theupdateframework/notary/tuf/data"
|
||||
"github.com/theupdateframework/notary/tuf/utils"
|
||||
)
|
||||
@ -77,7 +76,7 @@ func (r *repository) AddDelegationPaths(name data.RoleName, paths []string) erro
|
||||
}
|
||||
|
||||
// RemoveDelegationKeysAndPaths creates changelist entries to remove provided delegation key IDs and paths.
|
||||
// This method composes RemoveDelegationPaths and RemoveDelegationKeys (each creates one changelist if called).
|
||||
// This method composes RemoveDelegationPaths and RemoveDelegationKeys (each creates one changelist entry if called).
|
||||
func (r *repository) RemoveDelegationKeysAndPaths(name data.RoleName, keyIDs, paths []string) error {
|
||||
if len(paths) > 0 {
|
||||
err := r.RemoveDelegationPaths(name, paths)
|
||||
@ -201,41 +200,6 @@ func newDeleteDelegationChange(name data.RoleName, content []byte) *changelist.T
|
||||
)
|
||||
}
|
||||
|
||||
// GetDelegationRoles returns the keys and roles of the repository's delegations
|
||||
// Also converts key IDs to canonical key IDs to keep consistent with signing prompts
|
||||
func (r *repository) GetDelegationRoles() ([]data.Role, error) {
|
||||
// Update state of the repo to latest
|
||||
if err := r.Update(false); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// All top level delegations (ex: targets/level1) are stored exclusively in targets.json
|
||||
_, ok := r.tufRepo.Targets[data.CanonicalTargetsRole]
|
||||
if !ok {
|
||||
return nil, store.ErrMetaNotFound{Resource: data.CanonicalTargetsRole.String()}
|
||||
}
|
||||
|
||||
// make a copy for traversing nested delegations
|
||||
allDelegations := []data.Role{}
|
||||
|
||||
// Define a visitor function to populate the delegations list and translate their key IDs to canonical IDs
|
||||
delegationCanonicalListVisitor := func(tgt *data.SignedTargets, validRole data.DelegationRole) interface{} {
|
||||
// For the return list, update with a copy that includes canonicalKeyIDs
|
||||
// These aren't validated by the validRole
|
||||
canonicalDelegations, err := translateDelegationsToCanonicalIDs(tgt.Signed.Delegations)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
allDelegations = append(allDelegations, canonicalDelegations...)
|
||||
return nil
|
||||
}
|
||||
err := r.tufRepo.WalkTargets("", "", delegationCanonicalListVisitor)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return allDelegations, nil
|
||||
}
|
||||
|
||||
func translateDelegationsToCanonicalIDs(delegationInfo data.Delegations) ([]data.Role, error) {
|
||||
canonicalDelegations := make([]data.Role, len(delegationInfo.Roles))
|
||||
// Do a copy by value to ensure local delegation metadata is untouched
|
||||
|
||||
139
vendor/github.com/theupdateframework/notary/client/interface.go
generated
vendored
139
vendor/github.com/theupdateframework/notary/client/interface.go
generated
vendored
@ -6,42 +6,145 @@ import (
|
||||
"github.com/theupdateframework/notary/tuf/signed"
|
||||
)
|
||||
|
||||
// Repository represents the set of options that must be supported over a TUF repo.
|
||||
type Repository interface {
|
||||
// General management operations
|
||||
Initialize(rootKeyIDs []string, serverManagedRoles ...data.RoleName) error
|
||||
InitializeWithCertificate(rootKeyIDs []string, rootCerts []data.PublicKey, serverManagedRoles ...data.RoleName) error
|
||||
Publish() error
|
||||
|
||||
// Target Operations
|
||||
AddTarget(target *Target, roles ...data.RoleName) error
|
||||
RemoveTarget(targetName string, roles ...data.RoleName) error
|
||||
// ReadOnly represents the set of options that must be supported over a TUF repo for
|
||||
// reading
|
||||
type ReadOnly interface {
|
||||
// ListTargets lists all targets for the current repository. The list of
|
||||
// roles should be passed in order from highest to lowest priority.
|
||||
//
|
||||
// IMPORTANT: if you pass a set of roles such as [ "targets/a", "targets/x"
|
||||
// "targets/a/b" ], even though "targets/a/b" is part of the "targets/a" subtree
|
||||
// its entries will be strictly shadowed by those in other parts of the "targets/a"
|
||||
// subtree and also the "targets/x" subtree, as we will defer parsing it until
|
||||
// we explicitly reach it in our iteration of the provided list of roles.
|
||||
ListTargets(roles ...data.RoleName) ([]*TargetWithRole, error)
|
||||
|
||||
// GetTargetByName returns a target by the given name. If no roles are passed
|
||||
// it uses the targets role and does a search of the entire delegation
|
||||
// graph, finding the first entry in a breadth first search of the delegations.
|
||||
// If roles are passed, they should be passed in descending priority and
|
||||
// the target entry found in the subtree of the highest priority role
|
||||
// will be returned.
|
||||
// See the IMPORTANT section on ListTargets above. Those roles also apply here.
|
||||
GetTargetByName(name string, roles ...data.RoleName) (*TargetWithRole, error)
|
||||
|
||||
// GetAllTargetMetadataByName searches the entire delegation role tree to find
|
||||
// the specified target by name for all roles, and returns a list of
|
||||
// TargetSignedStructs for each time it finds the specified target.
|
||||
// If given an empty string for a target name, it will return back all targets
|
||||
// signed into the repository in every role
|
||||
GetAllTargetMetadataByName(name string) ([]TargetSignedStruct, error)
|
||||
|
||||
// Changelist operations
|
||||
// ListRoles returns a list of RoleWithSignatures objects for this repo
|
||||
// This represents the latest metadata for each role in this repo
|
||||
ListRoles() ([]RoleWithSignatures, error)
|
||||
|
||||
// GetDelegationRoles returns the keys and roles of the repository's delegations
|
||||
// Also converts key IDs to canonical key IDs to keep consistent with signing prompts
|
||||
GetDelegationRoles() ([]data.Role, error)
|
||||
}
|
||||
|
||||
// Repository represents the set of options that must be supported over a TUF repo
|
||||
// for both reading and writing.
|
||||
type Repository interface {
|
||||
ReadOnly
|
||||
|
||||
// ------------------- Publishing operations -------------------
|
||||
|
||||
// GetGUN returns the GUN associated with the repository
|
||||
GetGUN() data.GUN
|
||||
|
||||
// SetLegacyVersion sets the number of versions back to fetch roots to sign with
|
||||
SetLegacyVersions(int)
|
||||
|
||||
// ----- General management operations -----
|
||||
|
||||
// Initialize creates a new repository by using rootKey as the root Key for the
|
||||
// TUF repository. The remote store/server must be reachable (and is asked to
|
||||
// generate a timestamp key and possibly other serverManagedRoles), but the
|
||||
// created repository result is only stored on local cache, not published to
|
||||
// the remote store. To do that, use r.Publish() eventually.
|
||||
Initialize(rootKeyIDs []string, serverManagedRoles ...data.RoleName) error
|
||||
|
||||
// InitializeWithCertificate initializes the repository with root keys and their
|
||||
// corresponding certificates
|
||||
InitializeWithCertificate(rootKeyIDs []string, rootCerts []data.PublicKey, serverManagedRoles ...data.RoleName) error
|
||||
|
||||
// Publish pushes the local changes in signed material to the remote notary-server
|
||||
// Conceptually it performs an operation similar to a `git rebase`
|
||||
Publish() error
|
||||
|
||||
// ----- Target Operations -----
|
||||
|
||||
// AddTarget creates new changelist entries to add a target to the given roles
|
||||
// in the repository when the changelist gets applied at publish time.
|
||||
// If roles are unspecified, the default role is "targets"
|
||||
AddTarget(target *Target, roles ...data.RoleName) error
|
||||
|
||||
// RemoveTarget creates new changelist entries to remove a target from the given
|
||||
// roles in the repository when the changelist gets applied at publish time.
|
||||
// If roles are unspecified, the default role is "target".
|
||||
RemoveTarget(targetName string, roles ...data.RoleName) error
|
||||
|
||||
// ----- Changelist operations -----
|
||||
|
||||
// GetChangelist returns the list of the repository's unpublished changes
|
||||
GetChangelist() (changelist.Changelist, error)
|
||||
|
||||
// Role operations
|
||||
ListRoles() ([]RoleWithSignatures, error)
|
||||
GetDelegationRoles() ([]data.Role, error)
|
||||
// ----- Role operations -----
|
||||
|
||||
// AddDelegation creates changelist entries to add provided delegation public keys and paths.
|
||||
// This method composes AddDelegationRoleAndKeys and AddDelegationPaths (each creates one changelist if called).
|
||||
AddDelegation(name data.RoleName, delegationKeys []data.PublicKey, paths []string) error
|
||||
|
||||
// AddDelegationRoleAndKeys creates a changelist entry to add provided delegation public keys.
|
||||
// This method is the simplest way to create a new delegation, because the delegation must have at least
|
||||
// one key upon creation to be valid since we will reject the changelist while validating the threshold.
|
||||
AddDelegationRoleAndKeys(name data.RoleName, delegationKeys []data.PublicKey) error
|
||||
|
||||
// AddDelegationPaths creates a changelist entry to add provided paths to an existing delegation.
|
||||
// This method cannot create a new delegation itself because the role must meet the key threshold upon
|
||||
// creation.
|
||||
AddDelegationPaths(name data.RoleName, paths []string) error
|
||||
|
||||
// RemoveDelegationKeysAndPaths creates changelist entries to remove provided delegation key IDs and
|
||||
// paths. This method composes RemoveDelegationPaths and RemoveDelegationKeys (each creates one
|
||||
// changelist entry if called).
|
||||
RemoveDelegationKeysAndPaths(name data.RoleName, keyIDs, paths []string) error
|
||||
|
||||
// RemoveDelegationRole creates a changelist to remove all paths and keys from a role, and delete the
|
||||
// role in its entirety.
|
||||
RemoveDelegationRole(name data.RoleName) error
|
||||
|
||||
// RemoveDelegationPaths creates a changelist entry to remove provided paths from an existing delegation.
|
||||
RemoveDelegationPaths(name data.RoleName, paths []string) error
|
||||
|
||||
// RemoveDelegationKeys creates a changelist entry to remove provided keys from an existing delegation.
|
||||
// When this changelist is applied, if the specified keys are the only keys left in the role,
|
||||
// the role itself will be deleted in its entirety.
|
||||
// It can also delete a key from all delegations under a parent using a name
|
||||
// with a wildcard at the end.
|
||||
RemoveDelegationKeys(name data.RoleName, keyIDs []string) error
|
||||
|
||||
// ClearDelegationPaths creates a changelist entry to remove all paths from an existing delegation.
|
||||
ClearDelegationPaths(name data.RoleName) error
|
||||
|
||||
// Witness and other re-signing operations
|
||||
// ----- Witness and other re-signing operations -----
|
||||
|
||||
// Witness creates change objects to witness (i.e. re-sign) the given
|
||||
// roles on the next publish. One change is created per role
|
||||
Witness(roles ...data.RoleName) ([]data.RoleName, error)
|
||||
|
||||
// Key Operations
|
||||
// ----- Key Operations -----
|
||||
|
||||
// RotateKey removes all existing keys associated with the role. If no keys are
|
||||
// specified in keyList, then this creates and adds one new key or delegates
|
||||
// managing the key to the server. If key(s) are specified by keyList, then they are
|
||||
// used for signing the role.
|
||||
// These changes are staged in a changelist until publish is called.
|
||||
RotateKey(role data.RoleName, serverManagesKey bool, keyList []string) error
|
||||
|
||||
// GetCryptoService is the getter for the repository's CryptoService, which is used
|
||||
// to sign all updates.
|
||||
GetCryptoService() signed.CryptoService
|
||||
SetLegacyVersions(int)
|
||||
GetGUN() data.GUN
|
||||
}
|
||||
|
||||
257
vendor/github.com/theupdateframework/notary/client/reader.go
generated
vendored
Normal file
257
vendor/github.com/theupdateframework/notary/client/reader.go
generated
vendored
Normal file
@ -0,0 +1,257 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
canonicaljson "github.com/docker/go/canonical/json"
|
||||
store "github.com/theupdateframework/notary/storage"
|
||||
"github.com/theupdateframework/notary/tuf"
|
||||
"github.com/theupdateframework/notary/tuf/data"
|
||||
"github.com/theupdateframework/notary/tuf/utils"
|
||||
)
|
||||
|
||||
// Target represents a simplified version of the data TUF operates on, so external
|
||||
// applications don't have to depend on TUF data types.
|
||||
type Target struct {
|
||||
Name string // the name of the target
|
||||
Hashes data.Hashes // the hash of the target
|
||||
Length int64 // the size in bytes of the target
|
||||
Custom *canonicaljson.RawMessage // the custom data provided to describe the file at TARGETPATH
|
||||
}
|
||||
|
||||
// TargetWithRole represents a Target that exists in a particular role - this is
|
||||
// produced by ListTargets and GetTargetByName
|
||||
type TargetWithRole struct {
|
||||
Target
|
||||
Role data.RoleName
|
||||
}
|
||||
|
||||
// TargetSignedStruct is a struct that contains a Target, the role it was found in, and the list of signatures for that role
|
||||
type TargetSignedStruct struct {
|
||||
Role data.DelegationRole
|
||||
Target Target
|
||||
Signatures []data.Signature
|
||||
}
|
||||
|
||||
//ErrNoSuchTarget is returned when no valid trust data is found.
|
||||
type ErrNoSuchTarget string
|
||||
|
||||
func (f ErrNoSuchTarget) Error() string {
|
||||
return fmt.Sprintf("No valid trust data for %s", string(f))
|
||||
}
|
||||
|
||||
// RoleWithSignatures is a Role with its associated signatures
|
||||
type RoleWithSignatures struct {
|
||||
Signatures []data.Signature
|
||||
data.Role
|
||||
}
|
||||
|
||||
// NewReadOnly is the base method that returns a new notary repository for reading.
|
||||
// It expects an initialized cache. In case of a nil remote store, a default
|
||||
// offline store is used.
|
||||
func NewReadOnly(repo *tuf.Repo) ReadOnly {
|
||||
return &reader{tufRepo: repo}
|
||||
}
|
||||
|
||||
type reader struct {
|
||||
tufRepo *tuf.Repo
|
||||
}
|
||||
|
||||
// ListTargets lists all targets for the current repository. The list of
|
||||
// roles should be passed in order from highest to lowest priority.
|
||||
//
|
||||
// IMPORTANT: if you pass a set of roles such as [ "targets/a", "targets/x"
|
||||
// "targets/a/b" ], even though "targets/a/b" is part of the "targets/a" subtree
|
||||
// its entries will be strictly shadowed by those in other parts of the "targets/a"
|
||||
// subtree and also the "targets/x" subtree, as we will defer parsing it until
|
||||
// we explicitly reach it in our iteration of the provided list of roles.
|
||||
func (r *reader) ListTargets(roles ...data.RoleName) ([]*TargetWithRole, error) {
|
||||
if len(roles) == 0 {
|
||||
roles = []data.RoleName{data.CanonicalTargetsRole}
|
||||
}
|
||||
targets := make(map[string]*TargetWithRole)
|
||||
for _, role := range roles {
|
||||
// Define an array of roles to skip for this walk (see IMPORTANT comment above)
|
||||
skipRoles := utils.RoleNameSliceRemove(roles, role)
|
||||
|
||||
// Define a visitor function to populate the targets map in priority order
|
||||
listVisitorFunc := func(tgt *data.SignedTargets, validRole data.DelegationRole) interface{} {
|
||||
// We found targets so we should try to add them to our targets map
|
||||
for targetName, targetMeta := range tgt.Signed.Targets {
|
||||
// Follow the priority by not overriding previously set targets
|
||||
// and check that this path is valid with this role
|
||||
if _, ok := targets[targetName]; ok || !validRole.CheckPaths(targetName) {
|
||||
continue
|
||||
}
|
||||
targets[targetName] = &TargetWithRole{
|
||||
Target: Target{
|
||||
Name: targetName,
|
||||
Hashes: targetMeta.Hashes,
|
||||
Length: targetMeta.Length,
|
||||
Custom: targetMeta.Custom,
|
||||
},
|
||||
Role: validRole.Name,
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
r.tufRepo.WalkTargets("", role, listVisitorFunc, skipRoles...)
|
||||
}
|
||||
|
||||
var targetList []*TargetWithRole
|
||||
for _, v := range targets {
|
||||
targetList = append(targetList, v)
|
||||
}
|
||||
|
||||
return targetList, nil
|
||||
}
|
||||
|
||||
// GetTargetByName returns a target by the given name. If no roles are passed
|
||||
// it uses the targets role and does a search of the entire delegation
|
||||
// graph, finding the first entry in a breadth first search of the delegations.
|
||||
// If roles are passed, they should be passed in descending priority and
|
||||
// the target entry found in the subtree of the highest priority role
|
||||
// will be returned.
|
||||
// See the IMPORTANT section on ListTargets above. Those roles also apply here.
|
||||
func (r *reader) GetTargetByName(name string, roles ...data.RoleName) (*TargetWithRole, error) {
|
||||
if len(roles) == 0 {
|
||||
roles = append(roles, data.CanonicalTargetsRole)
|
||||
}
|
||||
var resultMeta data.FileMeta
|
||||
var resultRoleName data.RoleName
|
||||
var foundTarget bool
|
||||
for _, role := range roles {
|
||||
// Define an array of roles to skip for this walk (see IMPORTANT comment above)
|
||||
skipRoles := utils.RoleNameSliceRemove(roles, role)
|
||||
|
||||
// Define a visitor function to find the specified target
|
||||
getTargetVisitorFunc := func(tgt *data.SignedTargets, validRole data.DelegationRole) interface{} {
|
||||
if tgt == nil {
|
||||
return nil
|
||||
}
|
||||
// We found the target and validated path compatibility in our walk,
|
||||
// so we should stop our walk and set the resultMeta and resultRoleName variables
|
||||
if resultMeta, foundTarget = tgt.Signed.Targets[name]; foundTarget {
|
||||
resultRoleName = validRole.Name
|
||||
return tuf.StopWalk{}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
// Check that we didn't error, and that we assigned to our target
|
||||
if err := r.tufRepo.WalkTargets(name, role, getTargetVisitorFunc, skipRoles...); err == nil && foundTarget {
|
||||
return &TargetWithRole{Target: Target{Name: name, Hashes: resultMeta.Hashes, Length: resultMeta.Length, Custom: resultMeta.Custom}, Role: resultRoleName}, nil
|
||||
}
|
||||
}
|
||||
return nil, ErrNoSuchTarget(name)
|
||||
|
||||
}
|
||||
|
||||
// GetAllTargetMetadataByName searches the entire delegation role tree to find the specified target by name for all
|
||||
// roles, and returns a list of TargetSignedStructs for each time it finds the specified target.
|
||||
// If given an empty string for a target name, it will return back all targets signed into the repository in every role
|
||||
func (r *reader) GetAllTargetMetadataByName(name string) ([]TargetSignedStruct, error) {
|
||||
var targetInfoList []TargetSignedStruct
|
||||
|
||||
// Define a visitor function to find the specified target
|
||||
getAllTargetInfoByNameVisitorFunc := func(tgt *data.SignedTargets, validRole data.DelegationRole) interface{} {
|
||||
if tgt == nil {
|
||||
return nil
|
||||
}
|
||||
// We found a target and validated path compatibility in our walk,
|
||||
// so add it to our list if we have a match
|
||||
// if we have an empty name, add all targets, else check if we have it
|
||||
var targetMetaToAdd data.Files
|
||||
if name == "" {
|
||||
targetMetaToAdd = tgt.Signed.Targets
|
||||
} else {
|
||||
if meta, ok := tgt.Signed.Targets[name]; ok {
|
||||
targetMetaToAdd = data.Files{name: meta}
|
||||
}
|
||||
}
|
||||
|
||||
for targetName, resultMeta := range targetMetaToAdd {
|
||||
targetInfo := TargetSignedStruct{
|
||||
Role: validRole,
|
||||
Target: Target{Name: targetName, Hashes: resultMeta.Hashes, Length: resultMeta.Length, Custom: resultMeta.Custom},
|
||||
Signatures: tgt.Signatures,
|
||||
}
|
||||
targetInfoList = append(targetInfoList, targetInfo)
|
||||
}
|
||||
// continue walking to all child roles
|
||||
return nil
|
||||
}
|
||||
|
||||
// Check that we didn't error, and that we found the target at least once
|
||||
if err := r.tufRepo.WalkTargets(name, "", getAllTargetInfoByNameVisitorFunc); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(targetInfoList) == 0 {
|
||||
return nil, ErrNoSuchTarget(name)
|
||||
}
|
||||
return targetInfoList, nil
|
||||
}
|
||||
|
||||
// ListRoles returns a list of RoleWithSignatures objects for this repo
|
||||
// This represents the latest metadata for each role in this repo
|
||||
func (r *reader) ListRoles() ([]RoleWithSignatures, error) {
|
||||
// Get all role info from our updated keysDB, can be empty
|
||||
roles := r.tufRepo.GetAllLoadedRoles()
|
||||
|
||||
var roleWithSigs []RoleWithSignatures
|
||||
|
||||
// Populate RoleWithSignatures with Role from keysDB and signatures from TUF metadata
|
||||
for _, role := range roles {
|
||||
roleWithSig := RoleWithSignatures{Role: *role, Signatures: nil}
|
||||
switch role.Name {
|
||||
case data.CanonicalRootRole:
|
||||
roleWithSig.Signatures = r.tufRepo.Root.Signatures
|
||||
case data.CanonicalTargetsRole:
|
||||
roleWithSig.Signatures = r.tufRepo.Targets[data.CanonicalTargetsRole].Signatures
|
||||
case data.CanonicalSnapshotRole:
|
||||
roleWithSig.Signatures = r.tufRepo.Snapshot.Signatures
|
||||
case data.CanonicalTimestampRole:
|
||||
roleWithSig.Signatures = r.tufRepo.Timestamp.Signatures
|
||||
default:
|
||||
if !data.IsDelegation(role.Name) {
|
||||
continue
|
||||
}
|
||||
if _, ok := r.tufRepo.Targets[role.Name]; ok {
|
||||
// We'll only find a signature if we've published any targets with this delegation
|
||||
roleWithSig.Signatures = r.tufRepo.Targets[role.Name].Signatures
|
||||
}
|
||||
}
|
||||
roleWithSigs = append(roleWithSigs, roleWithSig)
|
||||
}
|
||||
return roleWithSigs, nil
|
||||
}
|
||||
|
||||
// GetDelegationRoles returns the keys and roles of the repository's delegations
|
||||
// Also converts key IDs to canonical key IDs to keep consistent with signing prompts
|
||||
func (r *reader) GetDelegationRoles() ([]data.Role, error) {
|
||||
// All top level delegations (ex: targets/level1) are stored exclusively in targets.json
|
||||
_, ok := r.tufRepo.Targets[data.CanonicalTargetsRole]
|
||||
if !ok {
|
||||
return nil, store.ErrMetaNotFound{Resource: data.CanonicalTargetsRole.String()}
|
||||
}
|
||||
|
||||
// make a copy for traversing nested delegations
|
||||
allDelegations := []data.Role{}
|
||||
|
||||
// Define a visitor function to populate the delegations list and translate their key IDs to canonical IDs
|
||||
delegationCanonicalListVisitor := func(tgt *data.SignedTargets, validRole data.DelegationRole) interface{} {
|
||||
// For the return list, update with a copy that includes canonicalKeyIDs
|
||||
// These aren't validated by the validRole
|
||||
canonicalDelegations, err := translateDelegationsToCanonicalIDs(tgt.Signed.Delegations)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
allDelegations = append(allDelegations, canonicalDelegations...)
|
||||
return nil
|
||||
}
|
||||
err := r.tufRepo.WalkTargets("", "", delegationCanonicalListVisitor)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return allDelegations, nil
|
||||
}
|
||||
160
vendor/github.com/theupdateframework/notary/client/tufclient.go
generated
vendored
160
vendor/github.com/theupdateframework/notary/client/tufclient.go
generated
vendored
@ -3,9 +3,11 @@ package client
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"regexp"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/theupdateframework/notary"
|
||||
"github.com/theupdateframework/notary/cryptoservice"
|
||||
store "github.com/theupdateframework/notary/storage"
|
||||
"github.com/theupdateframework/notary/trustpinning"
|
||||
"github.com/theupdateframework/notary/tuf"
|
||||
@ -21,16 +23,6 @@ type tufClient struct {
|
||||
newBuilder tuf.RepoBuilder
|
||||
}
|
||||
|
||||
// newTufClient initialized a tufClient with the given repo, remote source of content, and cache
|
||||
func newTufClient(oldBuilder, newBuilder tuf.RepoBuilder, remote store.RemoteStore, cache store.MetadataStore) *tufClient {
|
||||
return &tufClient{
|
||||
oldBuilder: oldBuilder,
|
||||
newBuilder: newBuilder,
|
||||
remote: remote,
|
||||
cache: cache,
|
||||
}
|
||||
}
|
||||
|
||||
// Update performs an update to the TUF repo as defined by the TUF spec
|
||||
func (c *tufClient) Update() (*tuf.Repo, *tuf.Repo, error) {
|
||||
// 1. Get timestamp
|
||||
@ -139,7 +131,7 @@ func (c *tufClient) updateRoot() error {
|
||||
|
||||
// Write newest to cache
|
||||
if err := c.cache.Set(data.CanonicalRootRole.String(), raw); err != nil {
|
||||
logrus.Debugf("unable to write %s to cache: %d.%s", newestVersion, data.CanonicalRootRole, err)
|
||||
logrus.Debugf("unable to write %d.%s to cache: %s", newestVersion, data.CanonicalRootRole, err)
|
||||
}
|
||||
logrus.Debugf("finished updating root files")
|
||||
return nil
|
||||
@ -323,3 +315,149 @@ func (c *tufClient) tryLoadRemote(consistentInfo tuf.ConsistentInfo, old []byte)
|
||||
}
|
||||
return raw, nil
|
||||
}
|
||||
|
||||
// TUFLoadOptions are provided to LoadTUFRepo, which loads a TUF repo from cache,
|
||||
// from a remote store, or both
|
||||
type TUFLoadOptions struct {
|
||||
GUN data.GUN
|
||||
TrustPinning trustpinning.TrustPinConfig
|
||||
CryptoService signed.CryptoService
|
||||
Cache store.MetadataStore
|
||||
RemoteStore store.RemoteStore
|
||||
AlwaysCheckInitialized bool
|
||||
}
|
||||
|
||||
// bootstrapClient attempts to bootstrap a root.json to be used as the trust
|
||||
// anchor for a repository. The checkInitialized argument indicates whether
|
||||
// we should always attempt to contact the server to determine if the repository
|
||||
// is initialized or not. If set to true, we will always attempt to download
|
||||
// and return an error if the remote repository errors.
|
||||
//
|
||||
// Populates a tuf.RepoBuilder with this root metadata. If the root metadata
|
||||
// downloaded is a newer version than what is on disk, then intermediate
|
||||
// versions will be downloaded and verified in order to rotate trusted keys
|
||||
// properly. Newer root metadata must always be signed with the previous
|
||||
// threshold and keys.
|
||||
//
|
||||
// Fails if the remote server is reachable and does not know the repo
|
||||
// (i.e. before any metadata has been published), in which case the error is
|
||||
// store.ErrMetaNotFound, or if the root metadata (from whichever source is used)
|
||||
// is not trusted.
|
||||
//
|
||||
// Returns a TUFClient for the remote server, which may not be actually
|
||||
// operational (if the URL is invalid but a root.json is cached).
|
||||
func bootstrapClient(l TUFLoadOptions) (*tufClient, error) {
|
||||
minVersion := 1
|
||||
// the old root on disk should not be validated against any trust pinning configuration
|
||||
// because if we have an old root, it itself is the thing that pins trust
|
||||
oldBuilder := tuf.NewRepoBuilder(l.GUN, l.CryptoService, trustpinning.TrustPinConfig{})
|
||||
|
||||
// by default, we want to use the trust pinning configuration on any new root that we download
|
||||
newBuilder := tuf.NewRepoBuilder(l.GUN, l.CryptoService, l.TrustPinning)
|
||||
|
||||
// Try to read root from cache first. We will trust this root until we detect a problem
|
||||
// during update which will cause us to download a new root and perform a rotation.
|
||||
// If we have an old root, and it's valid, then we overwrite the newBuilder to be one
|
||||
// preloaded with the old root or one which uses the old root for trust bootstrapping.
|
||||
if rootJSON, err := l.Cache.GetSized(data.CanonicalRootRole.String(), store.NoSizeLimit); err == nil {
|
||||
// if we can't load the cached root, fail hard because that is how we pin trust
|
||||
if err := oldBuilder.Load(data.CanonicalRootRole, rootJSON, minVersion, true); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// again, the root on disk is the source of trust pinning, so use an empty trust
|
||||
// pinning configuration
|
||||
newBuilder = tuf.NewRepoBuilder(l.GUN, l.CryptoService, trustpinning.TrustPinConfig{})
|
||||
|
||||
if err := newBuilder.Load(data.CanonicalRootRole, rootJSON, minVersion, false); err != nil {
|
||||
// Ok, the old root is expired - we want to download a new one. But we want to use the
|
||||
// old root to verify the new root, so bootstrap a new builder with the old builder
|
||||
// but use the trustpinning to validate the new root
|
||||
minVersion = oldBuilder.GetLoadedVersion(data.CanonicalRootRole)
|
||||
newBuilder = oldBuilder.BootstrapNewBuilderWithNewTrustpin(l.TrustPinning)
|
||||
}
|
||||
}
|
||||
|
||||
if !newBuilder.IsLoaded(data.CanonicalRootRole) || l.AlwaysCheckInitialized {
|
||||
// remoteErr was nil and we were not able to load a root from cache or
|
||||
// are specifically checking for initialization of the repo.
|
||||
|
||||
// if remote store successfully set up, try and get root from remote
|
||||
// We don't have any local data to determine the size of root, so try the maximum (though it is restricted at 100MB)
|
||||
tmpJSON, err := l.RemoteStore.GetSized(data.CanonicalRootRole.String(), store.NoSizeLimit)
|
||||
if err != nil {
|
||||
// we didn't have a root in cache and were unable to load one from
|
||||
// the server. Nothing we can do but error.
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !newBuilder.IsLoaded(data.CanonicalRootRole) {
|
||||
// we always want to use the downloaded root if we couldn't load from cache
|
||||
if err := newBuilder.Load(data.CanonicalRootRole, tmpJSON, minVersion, false); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = l.Cache.Set(data.CanonicalRootRole.String(), tmpJSON)
|
||||
if err != nil {
|
||||
// if we can't write cache we should still continue, just log error
|
||||
logrus.Errorf("could not save root to cache: %s", err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We can only get here if remoteErr != nil (hence we don't download any new root),
|
||||
// and there was no root on disk
|
||||
if !newBuilder.IsLoaded(data.CanonicalRootRole) {
|
||||
return nil, ErrRepoNotInitialized{}
|
||||
}
|
||||
|
||||
return &tufClient{
|
||||
oldBuilder: oldBuilder,
|
||||
newBuilder: newBuilder,
|
||||
remote: l.RemoteStore,
|
||||
cache: l.Cache,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// LoadTUFRepo bootstraps a trust anchor (root.json) from cache (if provided) before updating
|
||||
// all the metadata for the repo from the remote (if provided). It loads a TUF repo from cache,
|
||||
// from a remote store, or both.
|
||||
func LoadTUFRepo(options TUFLoadOptions) (*tuf.Repo, *tuf.Repo, error) {
|
||||
// set some sane defaults, so nothing has to be provided necessarily
|
||||
if options.RemoteStore == nil {
|
||||
options.RemoteStore = store.OfflineStore{}
|
||||
}
|
||||
if options.Cache == nil {
|
||||
options.Cache = store.NewMemoryStore(nil)
|
||||
}
|
||||
if options.CryptoService == nil {
|
||||
options.CryptoService = cryptoservice.EmptyService
|
||||
}
|
||||
|
||||
c, err := bootstrapClient(options)
|
||||
if err != nil {
|
||||
if _, ok := err.(store.ErrMetaNotFound); ok {
|
||||
return nil, nil, ErrRepositoryNotExist{
|
||||
remote: options.RemoteStore.Location(),
|
||||
gun: options.GUN,
|
||||
}
|
||||
}
|
||||
return nil, nil, err
|
||||
}
|
||||
repo, invalid, err := c.Update()
|
||||
if err != nil {
|
||||
// notFound.Resource may include a version or checksum so when the role is root,
|
||||
// it will be root, <version>.root or root.<checksum>.
|
||||
notFound, ok := err.(store.ErrMetaNotFound)
|
||||
isRoot, _ := regexp.MatchString(`\.?`+data.CanonicalRootRole.String()+`\.?`, notFound.Resource)
|
||||
if ok && isRoot {
|
||||
return nil, nil, ErrRepositoryNotExist{
|
||||
remote: options.RemoteStore.Location(),
|
||||
gun: options.GUN,
|
||||
}
|
||||
}
|
||||
return nil, nil, err
|
||||
}
|
||||
warnRolesNearExpiry(repo)
|
||||
return repo, invalid, nil
|
||||
}
|
||||
|
||||
3
vendor/github.com/theupdateframework/notary/cryptoservice/crypto_service.go
generated
vendored
3
vendor/github.com/theupdateframework/notary/cryptoservice/crypto_service.go
generated
vendored
@ -21,6 +21,9 @@ var (
|
||||
// ErrRootKeyNotEncrypted is returned if a root key being imported is
|
||||
// unencrypted
|
||||
ErrRootKeyNotEncrypted = errors.New("only encrypted root keys may be imported")
|
||||
|
||||
// EmptyService is an empty crypto service
|
||||
EmptyService = NewCryptoService()
|
||||
)
|
||||
|
||||
// CryptoService implements Sign and Create, holding a specific GUN and keystore to
|
||||
|
||||
2
vendor/github.com/theupdateframework/notary/fips.go
generated
vendored
2
vendor/github.com/theupdateframework/notary/fips.go
generated
vendored
@ -3,7 +3,7 @@ package notary
|
||||
import (
|
||||
"crypto"
|
||||
// Need to import md5 so can test availability.
|
||||
_ "crypto/md5"
|
||||
_ "crypto/md5" // #nosec
|
||||
)
|
||||
|
||||
// FIPSEnabled returns true if running in FIPS mode.
|
||||
|
||||
58
vendor/github.com/theupdateframework/notary/go.mod
generated
vendored
Normal file
58
vendor/github.com/theupdateframework/notary/go.mod
generated
vendored
Normal file
@ -0,0 +1,58 @@
|
||||
module github.com/theupdateframework/notary
|
||||
|
||||
go 1.12
|
||||
|
||||
require (
|
||||
github.com/BurntSushi/toml v0.3.1 // indirect
|
||||
github.com/Shopify/logrus-bugsnag v0.0.0-20170309145241-6dbc35f2c30d
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bitly/go-simplejson v0.5.0 // indirect
|
||||
github.com/bugsnag/bugsnag-go v1.0.5
|
||||
github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b // indirect
|
||||
github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0 // indirect
|
||||
github.com/cloudflare/cfssl v0.0.0-20180223231731-4e2dcbde5004 // 1.3.1
|
||||
github.com/denisenkom/go-mssqldb v0.0.0-20191128021309-1d7a30a10f73 // indirect
|
||||
github.com/docker/distribution v2.7.1+incompatible
|
||||
github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c
|
||||
github.com/docker/go-connections v0.4.0
|
||||
github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916 // indirect
|
||||
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 // indirect
|
||||
github.com/dvsekhvalnov/jose2go v0.0.0-20170216131308-f21a8cedbbae
|
||||
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 // indirect
|
||||
github.com/go-sql-driver/mysql v1.5.0
|
||||
github.com/gogo/protobuf v1.0.0 // indirect
|
||||
github.com/golang/protobuf v1.3.4
|
||||
github.com/google/certificate-transparency-go v1.0.10-0.20180222191210-5ab67e519c93 // indirect
|
||||
github.com/gorilla/mux v1.7.0
|
||||
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||
github.com/jinzhu/gorm v0.0.0-20170222002820-5409931a1bb8
|
||||
github.com/jinzhu/inflection v0.0.0-20170102125226-1c35d901db3d // indirect
|
||||
github.com/jinzhu/now v1.1.1 // indirect
|
||||
github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8 // indirect
|
||||
github.com/lib/pq v1.9.0
|
||||
github.com/magiconair/properties v1.5.3 // indirect
|
||||
github.com/mattn/go-sqlite3 v1.6.0
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
|
||||
github.com/miekg/pkcs11 v1.0.3
|
||||
github.com/mitchellh/mapstructure v1.0.0 // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.0.1 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/prometheus/client_golang v0.9.0-pre1.0.20180209125602-c332b6f63c06
|
||||
github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5 // indirect
|
||||
github.com/prometheus/common v0.0.0-20180110214958-89604d197083 // indirect
|
||||
github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7 // indirect
|
||||
github.com/sirupsen/logrus v1.8.1
|
||||
github.com/spf13/cast v0.0.0-20150508191742-4d07383ffe94 // indirect
|
||||
github.com/spf13/cobra v0.0.1
|
||||
github.com/spf13/jwalterweatherman v0.0.0-20141219030609-3d60171a6431 // indirect
|
||||
github.com/spf13/pflag v1.0.0 // indirect
|
||||
github.com/spf13/viper v0.0.0-20150530192845-be5ff3e4840c
|
||||
github.com/stretchr/testify v1.5.1
|
||||
golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3
|
||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221
|
||||
google.golang.org/grpc v1.0.5
|
||||
gopkg.in/rethinkdb/rethinkdb-go.v6 v6.2.1
|
||||
)
|
||||
8
vendor/github.com/theupdateframework/notary/passphrase/passphrase.go
generated
vendored
8
vendor/github.com/theupdateframework/notary/passphrase/passphrase.go
generated
vendored
@ -12,7 +12,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/theupdateframework/notary"
|
||||
"golang.org/x/crypto/ssh/terminal"
|
||||
"golang.org/x/term"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -49,7 +49,7 @@ var (
|
||||
// Upon successful passphrase retrievals, the passphrase will be cached such that
|
||||
// subsequent prompts will produce the same passphrase.
|
||||
func PromptRetriever() notary.PassRetriever {
|
||||
if !terminal.IsTerminal(int(os.Stdin.Fd())) {
|
||||
if !term.IsTerminal(int(os.Stdin.Fd())) {
|
||||
return func(string, string, bool, int) (string, bool, error) {
|
||||
return "", false, ErrNoInput
|
||||
}
|
||||
@ -200,8 +200,8 @@ func GetPassphrase(in *bufio.Reader) ([]byte, error) {
|
||||
err error
|
||||
)
|
||||
|
||||
if terminal.IsTerminal(int(os.Stdin.Fd())) {
|
||||
passphrase, err = terminal.ReadPassword(int(os.Stdin.Fd()))
|
||||
if term.IsTerminal(int(os.Stdin.Fd())) {
|
||||
passphrase, err = term.ReadPassword(int(os.Stdin.Fd()))
|
||||
} else {
|
||||
passphrase, err = in.ReadBytes('\n')
|
||||
}
|
||||
|
||||
6
vendor/github.com/theupdateframework/notary/storage/filestore.go
generated
vendored
6
vendor/github.com/theupdateframework/notary/storage/filestore.go
generated
vendored
@ -137,14 +137,16 @@ func (f *FilesystemStore) GetSized(name string, size int64) ([]byte, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
file, err := os.OpenFile(p, os.O_RDONLY, notary.PrivNoExecPerms)
|
||||
file, err := os.Open(p)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
err = ErrMetaNotFound{Resource: name}
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
defer file.Close()
|
||||
defer func() {
|
||||
_ = file.Close()
|
||||
}()
|
||||
|
||||
if size == NoSizeLimit {
|
||||
size = notary.MaxDownloadSize
|
||||
|
||||
14
vendor/github.com/theupdateframework/notary/storage/httpstore.go
generated
vendored
14
vendor/github.com/theupdateframework/notary/storage/httpstore.go
generated
vendored
@ -111,6 +111,18 @@ type HTTPStore struct {
|
||||
roundTrip http.RoundTripper
|
||||
}
|
||||
|
||||
// NewNotaryServerStore returns a new HTTPStore against a URL which should represent a notary
|
||||
// server
|
||||
func NewNotaryServerStore(serverURL string, gun data.GUN, roundTrip http.RoundTripper) (RemoteStore, error) {
|
||||
return NewHTTPStore(
|
||||
serverURL+"/v2/"+gun.String()+"/_trust/tuf/",
|
||||
"",
|
||||
"json",
|
||||
"key",
|
||||
roundTrip,
|
||||
)
|
||||
}
|
||||
|
||||
// NewHTTPStore initializes a new store against a URL and a number of configuration options.
|
||||
//
|
||||
// In case of a nil `roundTrip`, a default offline store is used instead.
|
||||
@ -363,5 +375,5 @@ func (s HTTPStore) RotateKey(role data.RoleName) ([]byte, error) {
|
||||
|
||||
// Location returns a human readable name for the storage location
|
||||
func (s HTTPStore) Location() string {
|
||||
return s.baseURL.String()
|
||||
return s.baseURL.Host
|
||||
}
|
||||
|
||||
1
vendor/github.com/theupdateframework/notary/storage/interfaces.go
generated
vendored
1
vendor/github.com/theupdateframework/notary/storage/interfaces.go
generated
vendored
@ -15,6 +15,7 @@ type MetadataStore interface {
|
||||
SetMulti(map[string][]byte) error
|
||||
RemoveAll() error
|
||||
Remove(name string) error
|
||||
Location() string
|
||||
}
|
||||
|
||||
// PublicKeyStore must be implemented by a key service
|
||||
|
||||
2
vendor/github.com/theupdateframework/notary/trustmanager/yubikey/pkcs11_darwin.go
generated
vendored
2
vendor/github.com/theupdateframework/notary/trustmanager/yubikey/pkcs11_darwin.go
generated
vendored
@ -6,4 +6,6 @@ var possiblePkcs11Libs = []string{
|
||||
"/usr/local/lib/libykcs11.dylib",
|
||||
"/usr/local/docker/lib/libykcs11.dylib",
|
||||
"/usr/local/docker-experimental/lib/libykcs11.dylib",
|
||||
// default location on arm64
|
||||
"/opt/homebrew/lib/libykcs11.dylib",
|
||||
}
|
||||
|
||||
2
vendor/github.com/theupdateframework/notary/tuf/builder.go
generated
vendored
2
vendor/github.com/theupdateframework/notary/tuf/builder.go
generated
vendored
@ -359,7 +359,7 @@ func (rb *repoBuilder) GenerateSnapshot(prev *data.SignedSnapshot) ([]byte, int,
|
||||
|
||||
// loadedNotChecksummed should currently contain the root awaiting checksumming,
|
||||
// since it has to have been loaded. Since the snapshot was generated using
|
||||
// the root and targets data (there may not be any) that that have been loaded,
|
||||
// the root and targets data (there may not be any) that have been loaded,
|
||||
// remove all of them from rb.loadedNotChecksummed
|
||||
for tgtName := range rb.repo.Targets {
|
||||
delete(rb.loadedNotChecksummed, data.RoleName(tgtName))
|
||||
|
||||
9
vendor/github.com/theupdateframework/notary/tuf/data/keys.go
generated
vendored
9
vendor/github.com/theupdateframework/notary/tuf/data/keys.go
generated
vendored
@ -12,9 +12,9 @@ import (
|
||||
"io"
|
||||
"math/big"
|
||||
|
||||
"github.com/agl/ed25519"
|
||||
"github.com/docker/go/canonical/json"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/crypto/ed25519"
|
||||
)
|
||||
|
||||
// PublicKey is the necessary interface for public keys
|
||||
@ -484,9 +484,10 @@ func (k RSAPrivateKey) Sign(rand io.Reader, msg []byte, opts crypto.SignerOpts)
|
||||
|
||||
// Sign creates an ed25519 signature
|
||||
func (k ED25519PrivateKey) Sign(rand io.Reader, msg []byte, opts crypto.SignerOpts) (signature []byte, err error) {
|
||||
priv := [ed25519.PrivateKeySize]byte{}
|
||||
copy(priv[:], k.private[ed25519.PublicKeySize:])
|
||||
return ed25519.Sign(&priv, msg)[:], nil
|
||||
priv := make([]byte, ed25519.PrivateKeySize)
|
||||
// The ed25519 key is serialized as public key then private key, so just use private key here.
|
||||
copy(priv, k.private[ed25519.PublicKeySize:])
|
||||
return ed25519.Sign(ed25519.PrivateKey(priv), msg)[:], nil
|
||||
}
|
||||
|
||||
// Sign on an UnknownPrivateKey raises an error because the client does not
|
||||
|
||||
2
vendor/github.com/theupdateframework/notary/tuf/data/roles.go
generated
vendored
2
vendor/github.com/theupdateframework/notary/tuf/data/roles.go
generated
vendored
@ -55,7 +55,7 @@ func (e ErrInvalidRole) Error() string {
|
||||
|
||||
// ValidRole only determines the name is semantically
|
||||
// correct. For target delegated roles, it does NOT check
|
||||
// the the appropriate parent roles exist.
|
||||
// the appropriate parent roles exist.
|
||||
func ValidRole(name RoleName) bool {
|
||||
if IsDelegation(name) {
|
||||
return true
|
||||
|
||||
2
vendor/github.com/theupdateframework/notary/tuf/data/snapshot.go
generated
vendored
2
vendor/github.com/theupdateframework/notary/tuf/data/snapshot.go
generated
vendored
@ -59,7 +59,7 @@ func IsValidSnapshotStructure(s Snapshot) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewSnapshot initilizes a SignedSnapshot with a given top level root
|
||||
// NewSnapshot initializes a SignedSnapshot with a given top level root
|
||||
// and targets objects
|
||||
func NewSnapshot(root *Signed, targets *Signed) (*SignedSnapshot, error) {
|
||||
logrus.Debug("generating new snapshot...")
|
||||
|
||||
2
vendor/github.com/theupdateframework/notary/tuf/data/targets.go
generated
vendored
2
vendor/github.com/theupdateframework/notary/tuf/data/targets.go
generated
vendored
@ -54,7 +54,7 @@ func isValidTargetsStructure(t Targets, roleName RoleName) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewTargets intiializes a new empty SignedTargets object
|
||||
// NewTargets initializes a new empty SignedTargets object
|
||||
func NewTargets() *SignedTargets {
|
||||
return &SignedTargets{
|
||||
Signatures: make([]Signature, 0),
|
||||
|
||||
2
vendor/github.com/theupdateframework/notary/tuf/data/types.go
generated
vendored
2
vendor/github.com/theupdateframework/notary/tuf/data/types.go
generated
vendored
@ -186,7 +186,7 @@ type FileMeta struct {
|
||||
|
||||
// Equals returns true if the other FileMeta object is equivalent to this one
|
||||
func (f FileMeta) Equals(o FileMeta) bool {
|
||||
if o.Length != f.Length || len(f.Hashes) != len(f.Hashes) {
|
||||
if o.Length != f.Length || len(o.Hashes) != len(f.Hashes) {
|
||||
return false
|
||||
}
|
||||
if f.Custom == nil && o.Custom != nil || f.Custom != nil && o.Custom == nil {
|
||||
|
||||
2
vendor/github.com/theupdateframework/notary/tuf/signed/interface.go
generated
vendored
2
vendor/github.com/theupdateframework/notary/tuf/signed/interface.go
generated
vendored
@ -39,7 +39,7 @@ type CryptoService interface {
|
||||
KeyService
|
||||
}
|
||||
|
||||
// Verifier defines an interface for verfying signatures. An implementer
|
||||
// Verifier defines an interface for verifying signatures. An implementer
|
||||
// of this interface should verify signatures for one and only one
|
||||
// signing scheme.
|
||||
type Verifier interface {
|
||||
|
||||
3
vendor/github.com/theupdateframework/notary/tuf/signed/sign.go
generated
vendored
3
vendor/github.com/theupdateframework/notary/tuf/signed/sign.go
generated
vendored
@ -87,7 +87,8 @@ func Sign(service CryptoService, s *data.Signed, signingKeys []data.PublicKey,
|
||||
})
|
||||
}
|
||||
|
||||
for _, sig := range s.Signatures {
|
||||
for i := range s.Signatures {
|
||||
sig := s.Signatures[i]
|
||||
if _, ok := signingKeyIDs[sig.KeyID]; ok {
|
||||
// key is in the set of key IDs for which a signature has been created
|
||||
continue
|
||||
|
||||
12
vendor/github.com/theupdateframework/notary/tuf/signed/verifiers.go
generated
vendored
12
vendor/github.com/theupdateframework/notary/tuf/signed/verifiers.go
generated
vendored
@ -10,9 +10,9 @@ import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
"github.com/agl/ed25519"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/theupdateframework/notary/tuf/data"
|
||||
"golang.org/x/crypto/ed25519"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -39,26 +39,26 @@ func (v Ed25519Verifier) Verify(key data.PublicKey, sig []byte, msg []byte) erro
|
||||
if key.Algorithm() != data.ED25519Key {
|
||||
return ErrInvalidKeyType{}
|
||||
}
|
||||
var sigBytes [ed25519.SignatureSize]byte
|
||||
sigBytes := make([]byte, ed25519.SignatureSize)
|
||||
if len(sig) != ed25519.SignatureSize {
|
||||
logrus.Debugf("signature length is incorrect, must be %d, was %d.", ed25519.SignatureSize, len(sig))
|
||||
return ErrInvalid
|
||||
}
|
||||
copy(sigBytes[:], sig)
|
||||
copy(sigBytes, sig)
|
||||
|
||||
var keyBytes [ed25519.PublicKeySize]byte
|
||||
keyBytes := make([]byte, ed25519.PublicKeySize)
|
||||
pub := key.Public()
|
||||
if len(pub) != ed25519.PublicKeySize {
|
||||
logrus.Errorf("public key is incorrect size, must be %d, was %d.", ed25519.PublicKeySize, len(pub))
|
||||
return ErrInvalidKeyLength{msg: fmt.Sprintf("ed25519 public key must be %d bytes.", ed25519.PublicKeySize)}
|
||||
}
|
||||
n := copy(keyBytes[:], key.Public())
|
||||
n := copy(keyBytes, key.Public())
|
||||
if n < ed25519.PublicKeySize {
|
||||
logrus.Errorf("failed to copy the key, must have %d bytes, copied %d bytes.", ed25519.PublicKeySize, n)
|
||||
return ErrInvalid
|
||||
}
|
||||
|
||||
if !ed25519.Verify(&keyBytes, msg, &sigBytes) {
|
||||
if !ed25519.Verify(ed25519.PublicKey(keyBytes), msg, sigBytes) {
|
||||
logrus.Debugf("failed ed25519 verification")
|
||||
return ErrInvalid
|
||||
}
|
||||
|
||||
2
vendor/github.com/theupdateframework/notary/tuf/utils/pkcs8.go
generated
vendored
2
vendor/github.com/theupdateframework/notary/tuf/utils/pkcs8.go
generated
vendored
@ -39,7 +39,7 @@ import (
|
||||
"crypto/elliptic"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/sha1"
|
||||
"crypto/sha1" // #nosec
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/asn1"
|
||||
|
||||
2
vendor/github.com/theupdateframework/notary/tuf/utils/utils.go
generated
vendored
2
vendor/github.com/theupdateframework/notary/tuf/utils/utils.go
generated
vendored
@ -30,7 +30,7 @@ func RoleNameSliceContains(ss []data.RoleName, s data.RoleName) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// RoleNameSliceRemove removes the the given RoleName from the slice, returning a new slice
|
||||
// RoleNameSliceRemove removes the given RoleName from the slice, returning a new slice
|
||||
func RoleNameSliceRemove(ss []data.RoleName, s data.RoleName) []data.RoleName {
|
||||
res := []data.RoleName{}
|
||||
for _, v := range ss {
|
||||
|
||||
2
vendor/github.com/theupdateframework/notary/tuf/utils/x509.go
generated
vendored
2
vendor/github.com/theupdateframework/notary/tuf/utils/x509.go
generated
vendored
@ -16,10 +16,10 @@ import (
|
||||
"math/big"
|
||||
"time"
|
||||
|
||||
"github.com/agl/ed25519"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/theupdateframework/notary"
|
||||
"github.com/theupdateframework/notary/tuf/data"
|
||||
"golang.org/x/crypto/ed25519"
|
||||
)
|
||||
|
||||
// CanonicalKeyID returns the ID of the public bytes version of a TUF key.
|
||||
|
||||
59
vendor/github.com/theupdateframework/notary/vendor.conf
generated
vendored
59
vendor/github.com/theupdateframework/notary/vendor.conf
generated
vendored
@ -1,59 +0,0 @@
|
||||
github.com/Shopify/logrus-bugsnag 6dbc35f2c30d1e37549f9673dd07912452ab28a5
|
||||
github.com/sirupsen/logrus f006c2ac4710855cf0f916dd6b77acf6b048dc6e # v1.0.3
|
||||
github.com/agl/ed25519 278e1ec8e8a6e017cd07577924d6766039146ced
|
||||
github.com/bugsnag/bugsnag-go 13fd6b8acda029830ef9904df6b63be0a83369d0
|
||||
github.com/bugsnag/panicwrap e2c28503fcd0675329da73bf48b33404db873782
|
||||
github.com/bugsnag/osext 0dd3f918b21bec95ace9dc86c7e70266cfc5c702
|
||||
github.com/docker/distribution edc3ab29cdff8694dd6feb85cfeb4b5f1b38ed9c
|
||||
github.com/opencontainers/go-digest a6d0ee40d4207ea02364bd3b9e8e77b9159ba1eb
|
||||
github.com/docker/go-connections 7395e3f8aa162843a74ed6d48e79627d9792ac55
|
||||
github.com/docker/go d30aec9fd63c35133f8f79c3412ad91a3b08be06
|
||||
github.com/dvsekhvalnov/jose2go f21a8cedbbae609f623613ec8f81125c243212e6 # v1.3
|
||||
github.com/go-sql-driver/mysql a0583e0143b1624142adab07e0e97fe106d99561 # v1.3
|
||||
github.com/gorilla/mux 53c1911da2b537f792e7cafcb446b05ffe33b996 # v1.6.1
|
||||
github.com/jinzhu/gorm 5409931a1bb87e484d68d649af9367c207713ea2
|
||||
github.com/jinzhu/inflection 1c35d901db3da928c72a72d8458480cc9ade058f
|
||||
github.com/lib/pq 0dad96c0b94f8dee039aa40467f767467392a0af
|
||||
github.com/mattn/go-sqlite3 6c771bb9887719704b210e87e934f08be014bdb1 # v1.6.0
|
||||
github.com/miekg/pkcs11 5f6e0d0dad6f472df908c8e968a98ef00c9224bb
|
||||
github.com/prometheus/client_golang 449ccefff16c8e2b7229f6be1921ba22f62461fe
|
||||
github.com/prometheus/client_model fa8ad6fec33561be4280a8f0514318c79d7f6cb6 # model-0.0.2-12-gfa8ad6f
|
||||
github.com/prometheus/procfs b1afdc266f54247f5dc725544f5d351a8661f502
|
||||
github.com/prometheus/common 4fdc91a58c9d3696b982e8a680f4997403132d44
|
||||
github.com/golang/protobuf c3cefd437628a0b7d31b34fe44b3a7a540e98527
|
||||
github.com/spf13/cobra 7b2c5ac9fc04fc5efafb60700713d4fa609b777b # v0.0.1
|
||||
github.com/spf13/viper be5ff3e4840cf692388bde7a057595a474ef379e
|
||||
golang.org/x/crypto 76eec36fa14229c4b25bb894c2d0e591527af429
|
||||
golang.org/x/net 6a513affb38dc9788b449d59ffed099b8de18fa0
|
||||
golang.org/x/sys 314a259e304ff91bd6985da2a7149bbf91237993
|
||||
google.golang.org/grpc 708a7f9f3283aa2d4f6132d287d78683babe55c8 # v1.0.5
|
||||
github.com/pkg/errors 839d9e913e063e28dfd0e6c7b7512793e0a48be9
|
||||
|
||||
github.com/spf13/pflag e57e3eeb33f795204c1ca35f56c44f83227c6e66 # v1.0.0
|
||||
github.com/spf13/cast 4d07383ffe94b5e5a6fa3af9211374a4507a0184
|
||||
gopkg.in/yaml.v2 5420a8b6744d3b0345ab293f6fcba19c978f1183 # v2.2.1
|
||||
gopkg.in/fatih/pool.v2 cba550ebf9bce999a02e963296d4bc7a486cb715
|
||||
github.com/gorilla/context 14f550f51af52180c2eefed15e5fd18d63c0a64a # unused
|
||||
github.com/spf13/jwalterweatherman 3d60171a64319ef63c78bd45bd60e6eab1e75f8b
|
||||
github.com/mitchellh/mapstructure 2caf8efc93669b6c43e0441cdc6aed17546c96f3
|
||||
github.com/magiconair/properties 624009598839a9432bd97bb75552389422357723 # v1.5.3
|
||||
github.com/kr/text 6807e777504f54ad073ecef66747de158294b639
|
||||
github.com/kr/pretty bc9499caa0f45ee5edb2f0209fbd61fbf3d9018f # go.weekly.2011-12-22-18-gbc9499c
|
||||
github.com/hailocab/go-hostpool e80d13ce29ede4452c43dea11e79b9bc8a15b478
|
||||
github.com/docker/libtrust aabc10ec26b754e797f9028f4589c5b7bd90dc20
|
||||
github.com/beorn7/perks b965b613227fddccbfffe13eae360ed3fa822f8d
|
||||
github.com/BurntSushi/toml a368813c5e648fee92e5f6c30e3944ff9d5e8895
|
||||
|
||||
github.com/matttproud/golang_protobuf_extensions d0c3fe89de86839aecf2e0579c40ba3bb336a453
|
||||
github.com/inconshreveable/mousetrap 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75
|
||||
|
||||
gopkg.in/dancannon/gorethink.v3 e324d6ad938205da6c1e8a0179dc97a5b1a92185 https://github.com/docker/gorethink # v3.0.0-logrus
|
||||
# dependencies of gorethink.v3
|
||||
gopkg.in/gorethink/gorethink.v2 ac5be4ae8538d44ae8843b97fc9f90860cb48a85 https://github.com/docker/gorethink # v2.2.2-logrus
|
||||
github.com/cenk/backoff 32cd0c5b3aef12c76ed64aaf678f6c79736be7dc # v1.0.0
|
||||
|
||||
# Testing requirements
|
||||
github.com/stretchr/testify 089c7181b8c728499929ff09b62d3fdd8df8adff
|
||||
github.com/cloudflare/cfssl 4e2dcbde500472449917533851bf4bae9bdff562 # v1.3.1
|
||||
github.com/google/certificate-transparency-go 5ab67e519c93568ac3ee50fd6772a5bcf8aa460d
|
||||
github.com/gogo/protobuf 1adfc126b41513cc696b209667c8656ea7aac67c # v1.0.0
|
||||
2
vendor/golang.org/x/sys/README.md
generated
vendored
2
vendor/golang.org/x/sys/README.md
generated
vendored
@ -1,5 +1,7 @@
|
||||
# sys
|
||||
|
||||
[](https://pkg.go.dev/golang.org/x/sys)
|
||||
|
||||
This repository holds supplemental Go packages for low-level interactions with
|
||||
the operating system.
|
||||
|
||||
|
||||
2
vendor/golang.org/x/sys/cpu/asm_aix_ppc64.s
generated
vendored
2
vendor/golang.org/x/sys/cpu/asm_aix_ppc64.s
generated
vendored
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
||||
40
vendor/golang.org/x/sys/cpu/cpu_arm64.go
generated
vendored
40
vendor/golang.org/x/sys/cpu/cpu_arm64.go
generated
vendored
@ -39,34 +39,34 @@ func initOptions() {
|
||||
|
||||
func archInit() {
|
||||
switch runtime.GOOS {
|
||||
case "android", "darwin", "ios", "netbsd", "openbsd":
|
||||
// Android and iOS don't seem to allow reading these registers.
|
||||
//
|
||||
// NetBSD:
|
||||
// ID_AA64ISAR0_EL1 is a privileged register and cannot be read from EL0.
|
||||
// It can be read via sysctl(3). Example for future implementers:
|
||||
// https://nxr.netbsd.org/xref/src/usr.sbin/cpuctl/arch/aarch64.c
|
||||
case "freebsd":
|
||||
readARM64Registers()
|
||||
case "linux", "netbsd":
|
||||
doinit()
|
||||
default:
|
||||
// Most platforms don't seem to allow reading these registers.
|
||||
//
|
||||
// OpenBSD:
|
||||
// See https://golang.org/issue/31746
|
||||
//
|
||||
// Fake the minimal features expected by
|
||||
// TestARM64minimalFeatures.
|
||||
ARM64.HasASIMD = true
|
||||
ARM64.HasFP = true
|
||||
case "linux":
|
||||
doinit()
|
||||
default:
|
||||
readARM64Registers()
|
||||
setMinimalFeatures()
|
||||
}
|
||||
}
|
||||
|
||||
// setMinimalFeatures fakes the minimal ARM64 features expected by
|
||||
// TestARM64minimalFeatures.
|
||||
func setMinimalFeatures() {
|
||||
ARM64.HasASIMD = true
|
||||
ARM64.HasFP = true
|
||||
}
|
||||
|
||||
func readARM64Registers() {
|
||||
Initialized = true
|
||||
|
||||
// ID_AA64ISAR0_EL1
|
||||
isar0 := getisar0()
|
||||
parseARM64SystemRegisters(getisar0(), getisar1(), getpfr0())
|
||||
}
|
||||
|
||||
func parseARM64SystemRegisters(isar0, isar1, pfr0 uint64) {
|
||||
// ID_AA64ISAR0_EL1
|
||||
switch extractBits(isar0, 4, 7) {
|
||||
case 1:
|
||||
ARM64.HasAES = true
|
||||
@ -124,8 +124,6 @@ func readARM64Registers() {
|
||||
}
|
||||
|
||||
// ID_AA64ISAR1_EL1
|
||||
isar1 := getisar1()
|
||||
|
||||
switch extractBits(isar1, 0, 3) {
|
||||
case 1:
|
||||
ARM64.HasDCPOP = true
|
||||
@ -147,8 +145,6 @@ func readARM64Registers() {
|
||||
}
|
||||
|
||||
// ID_AA64PFR0_EL1
|
||||
pfr0 := getpfr0()
|
||||
|
||||
switch extractBits(pfr0, 16, 19) {
|
||||
case 0:
|
||||
ARM64.HasFP = true
|
||||
|
||||
2
vendor/golang.org/x/sys/cpu/cpu_arm64.s
generated
vendored
2
vendor/golang.org/x/sys/cpu/cpu_arm64.s
generated
vendored
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user