From b569dc11a0638a888e7ebd2cafe71b0ce600f728 Mon Sep 17 00:00:00 2001 From: Yury Stankevich Date: Sat, 16 Jan 2021 18:52:08 +0300 Subject: [PATCH] hdfs: support kerberos authentication #42 --- backend/hdfs/fs.go | 69 ++++++++++++++++++- backend/hdfs/hdfs.go | 34 ++++++++- docs/content/hdfs.md | 32 +++++++++ fstest/testserver/images/test-hdfs/Dockerfile | 9 ++- fstest/testserver/images/test-hdfs/README.md | 33 +++++++-- .../testserver/images/test-hdfs/core-site.xml | 6 ++ .../testserver/images/test-hdfs/hdfs-site.xml | 17 +++++ fstest/testserver/images/test-hdfs/kdc.conf | 4 ++ fstest/testserver/images/test-hdfs/krb5.conf | 10 +++ fstest/testserver/images/test-hdfs/run.sh | 25 +++++++ fstest/testserver/init.d/TestHdfs | 15 +++- go.mod | 5 +- go.sum | 26 +++++++ 13 files changed, 269 insertions(+), 16 deletions(-) create mode 100644 fstest/testserver/images/test-hdfs/kdc.conf create mode 100644 fstest/testserver/images/test-hdfs/krb5.conf diff --git a/backend/hdfs/fs.go b/backend/hdfs/fs.go index ea82060aa..bdae0b12c 100644 --- a/backend/hdfs/fs.go +++ b/backend/hdfs/fs.go @@ -7,10 +7,15 @@ import ( "fmt" "io" "os" + "os/user" "path" + "strings" "time" "github.com/colinmarc/hdfs/v2" + krb "github.com/jcmturner/gokrb5/v8/client" + "github.com/jcmturner/gokrb5/v8/config" + "github.com/jcmturner/gokrb5/v8/credentials" "github.com/rclone/rclone/fs" "github.com/rclone/rclone/fs/config/configmap" "github.com/rclone/rclone/fs/config/configstruct" @@ -27,6 +32,49 @@ type Fs struct { client *hdfs.Client } +// copy-paste from https://github.com/colinmarc/hdfs/blob/master/cmd/hdfs/kerberos.go +func getKerberosClient() (*krb.Client, error) { + configPath := os.Getenv("KRB5_CONFIG") + if configPath == "" { + configPath = "/etc/krb5.conf" + } + + cfg, err := config.Load(configPath) + if err != nil { + return nil, err + } + + // Determine the ccache location from the environment, falling back to the + // default location. + ccachePath := os.Getenv("KRB5CCNAME") + if strings.Contains(ccachePath, ":") { + if strings.HasPrefix(ccachePath, "FILE:") { + ccachePath = strings.SplitN(ccachePath, ":", 2)[1] + } else { + return nil, fmt.Errorf("unusable ccache: %s", ccachePath) + } + } else if ccachePath == "" { + u, err := user.Current() + if err != nil { + return nil, err + } + + ccachePath = fmt.Sprintf("/tmp/krb5cc_%s", u.Uid) + } + + ccache, err := credentials.LoadCCache(ccachePath) + if err != nil { + return nil, err + } + + client, err := krb.NewFromCCache(ccache, cfg) + if err != nil { + return nil, err + } + + return client, nil +} + // NewFs constructs an Fs from the path func NewFs(ctx context.Context, name, root string, m configmap.Mapper) (fs.Fs, error) { opt := new(Options) @@ -35,11 +83,26 @@ func NewFs(ctx context.Context, name, root string, m configmap.Mapper) (fs.Fs, e return nil, err } - client, err := hdfs.NewClient(hdfs.ClientOptions{ + options := hdfs.ClientOptions{ Addresses: []string{opt.Namenode}, - User: opt.Username, UseDatanodeHostname: false, - }) + } + + if opt.ServicePrincipalName != "" { + options.KerberosClient, err = getKerberosClient() + if err != nil { + return nil, fmt.Errorf("Problem with kerberos authentication: %s", err) + } + options.KerberosServicePrincipleName = opt.ServicePrincipalName + + if opt.DataTransferProtection != "" { + options.DataTransferProtection = opt.DataTransferProtection + } + } else { + options.User = opt.Username + } + + client, err := hdfs.NewClient(options) if err != nil { return nil, err } diff --git a/backend/hdfs/hdfs.go b/backend/hdfs/hdfs.go index 29dd4da2d..24dff3091 100644 --- a/backend/hdfs/hdfs.go +++ b/backend/hdfs/hdfs.go @@ -32,6 +32,32 @@ func init() { Value: "root", Help: "Connect to hdfs as root", }}, + }, { + Name: "service_principal_name", + Help: `Kerberos service principal name for the namenode + +Enables KERBEROS authentication. Specifies the Service Principal Name +(/) for the namenode.`, + Required: false, + Examples: []fs.OptionExample{{ + Value: "hdfs/namenode.hadoop.docker", + Help: "Namenode running as service 'hdfs' with FQDN 'namenode.hadoop.docker'.", + }}, + Advanced: true, + }, { + Name: "data_transfer_protection", + Help: `Kerberos data transfer protection: authentication|integrity|privacy + +Specifies whether or not authentication, data signature integrity +checks, and wire encryption is required when communicating the the +datanodes. Possible values are 'authentication', 'integrity' and +'privacy'. Used only with KERBEROS enabled.`, + Required: false, + Examples: []fs.OptionExample{{ + Value: "privacy", + Help: "Ensure authentication, integrity and encryption enabled.", + }}, + Advanced: true, }, { Name: config.ConfigEncoding, Help: config.ConfigEncodingHelp, @@ -44,9 +70,11 @@ func init() { // Options for this backend type Options struct { - Namenode string `config:"namenode"` - Username string `config:"username"` - Enc encoder.MultiEncoder `config:"encoding"` + Namenode string `config:"namenode"` + Username string `config:"username"` + ServicePrincipalName string `config:"service_principal_name"` + DataTransferProtection string `config:"data_transfer_protection"` + Enc encoder.MultiEncoder `config:"encoding"` } // xPath make correct file path with leading '/' diff --git a/docs/content/hdfs.md b/docs/content/hdfs.md index 1fd075102..da92311a4 100644 --- a/docs/content/hdfs.md +++ b/docs/content/hdfs.md @@ -185,6 +185,38 @@ hadoop user name Here are the advanced options specific to hdfs (Hadoop distributed file system). +#### --hdfs-service-principal-name + +Kerberos service principal name for the namenode + +Enables KERBEROS authentication. Specifies the Service Principal Name +(SERVICE>/) for the namenode. + +- Config: service_principal_name +- Env Var: RCLONE_HDFS_SERVICE_PRINCIPAL_NAME +- Type: string +- Default: "" +- Examples: + - "hdfs/namenode.hadoop.docker" + - Namenode running as service 'hdfs' with FQDN 'namenode.hadoop.docker'. + +#### --hdfs-data-transfer-protection + +Kerberos data transfer protection: authentication|integrity|privacy + +Specifies whether or not authentication, data signature integrity +checks, and wire encryption is required when communicating the the +datanodes. Possible values are 'authentication', 'integrity' and +'privacy'. Used only with KERBEROS enabled. + +- Config: data_transfer_protection +- Env Var: RCLONE_HDFS_DATA_TRANSFER_PROTECTION +- Type: string +- Default: "" +- Examples: + - "privacy" + - Ensure authentication, integrity and encryption enabled. + #### --hdfs-encoding This sets the encoding for the backend. diff --git a/fstest/testserver/images/test-hdfs/Dockerfile b/fstest/testserver/images/test-hdfs/Dockerfile index 2fd759cd0..07c621d2e 100644 --- a/fstest/testserver/images/test-hdfs/Dockerfile +++ b/fstest/testserver/images/test-hdfs/Dockerfile @@ -3,12 +3,11 @@ FROM debian:stretch RUN apt-get update \ && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends openjdk-8-jdk \ + net-tools curl python krb5-user krb5-kdc krb5-admin-server \ && rm -rf /var/lib/apt/lists/* ENV JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64/ -RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends net-tools curl python - ENV HADOOP_VERSION 3.2.1 ENV HADOOP_URL https://www.apache.org/dist/hadoop/common/hadoop-$HADOOP_VERSION/hadoop-$HADOOP_VERSION.tar.gz RUN set -x \ @@ -37,6 +36,10 @@ ADD kms-site.xml /etc/hadoop/kms-site.xml ADD mapred-site.xml /etc/hadoop/mapred-site.xml ADD yarn-site.xml /etc/hadoop/yarn-site.xml +ADD krb5.conf /etc/ +ADD kdc.conf /etc/krb5kdc/ +RUN echo '*/admin@KERBEROS.RCLONE *' > /etc/krb5kdc/kadm5.acl + ADD run.sh /run.sh RUN chmod a+x /run.sh -CMD ["/run.sh"] \ No newline at end of file +CMD ["/run.sh"] diff --git a/fstest/testserver/images/test-hdfs/README.md b/fstest/testserver/images/test-hdfs/README.md index 52b6673ac..1f760ddbd 100644 --- a/fstest/testserver/images/test-hdfs/README.md +++ b/fstest/testserver/images/test-hdfs/README.md @@ -26,7 +26,32 @@ cd backend/hdfs GO111MODULE=on go test -v ``` -stop docker image: -``` -docker kill rclone-hdfs -``` +hdfs logs will be available in `.stdout.log` and `.stderr.log` + +# Kerberos + +test can be run against kerberos-enabled hdfs + +1. configure local krb5.conf + ``` + [libdefaults] + default_realm = KERBEROS.RCLONE + [realms] + KERBEROS.RCLONE = { + kdc = localhost + } + ``` + +2. enable kerberos in remote configuration + ``` + [TestHdfs] + ... + service_principal_name = hdfs/localhost + data_transfer_protection = privacy + ``` + +3. run test + ``` + cd backend/hdfs + KERBEROS=true GO111MODULE=on go test -v + ``` \ No newline at end of file diff --git a/fstest/testserver/images/test-hdfs/core-site.xml b/fstest/testserver/images/test-hdfs/core-site.xml index 3a046d246..061d48d46 100644 --- a/fstest/testserver/images/test-hdfs/core-site.xml +++ b/fstest/testserver/images/test-hdfs/core-site.xml @@ -3,4 +3,10 @@ hadoop.http.staticuser.userroot hadoop.proxyuser.root.groupsroot,nogroup hadoop.proxyuser.root.hosts* + + hadoop.security.authenticationkerberos + hadoop.security.authorizationtrue + hadoop.rpc.protectionintegrity + hadoop.user.group.static.mapping.overridesuser=supergroup + diff --git a/fstest/testserver/images/test-hdfs/hdfs-site.xml b/fstest/testserver/images/test-hdfs/hdfs-site.xml index 481f4c8af..3f3f3a6c0 100644 --- a/fstest/testserver/images/test-hdfs/hdfs-site.xml +++ b/fstest/testserver/images/test-hdfs/hdfs-site.xml @@ -11,4 +11,21 @@ dfs.namenode.servicerpc-bind-host0.0.0.0 dfs.replication2 nfs.dump.dir/tmp + + ignore.secure.ports.for.testingtrue + dfs.safemode.extension0 + dfs.block.access.token.enabletrue + + dfs.encrypt.data.transfertrue + dfs.encrypt.data.transfer.algorithmrc4 + dfs.encrypt.data.transfer.cipher.suitesAES/CTR/NoPadding + + dfs.namenode.kerberos.principal hdfs/_HOST@KERBEROS.RCLONE + dfs.web.authentication.kerberos.principalHTTP/_HOST@KERBEROS.RCLONE + dfs.datanode.kerberos.principal hdfs/_HOST@KERBEROS.RCLONE + + dfs.namenode.keytab.file /etc/hadoop/kerberos.key + dfs.web.authentication.kerberos.keytab/etc/hadoop/kerberos.key + dfs.datanode.keytab.file /etc/hadoop/kerberos.key + diff --git a/fstest/testserver/images/test-hdfs/kdc.conf b/fstest/testserver/images/test-hdfs/kdc.conf new file mode 100644 index 000000000..9eeb0bb9a --- /dev/null +++ b/fstest/testserver/images/test-hdfs/kdc.conf @@ -0,0 +1,4 @@ +[realms] + KERBEROS.RCLONE = { + acl_file = /etc/krb5kdc/kadm5.acl + } diff --git a/fstest/testserver/images/test-hdfs/krb5.conf b/fstest/testserver/images/test-hdfs/krb5.conf new file mode 100644 index 000000000..012950b4a --- /dev/null +++ b/fstest/testserver/images/test-hdfs/krb5.conf @@ -0,0 +1,10 @@ +[libdefaults] + default_realm = KERBEROS.RCLONE + dns_lookup_realm = false + dns_lookup_kdc = false + forwardable = true + proxiable = true +[realms] + KERBEROS.RCLONE = { + kdc = localhost + } diff --git a/fstest/testserver/images/test-hdfs/run.sh b/fstest/testserver/images/test-hdfs/run.sh index 48bd3b1ff..0009c6306 100755 --- a/fstest/testserver/images/test-hdfs/run.sh +++ b/fstest/testserver/images/test-hdfs/run.sh @@ -1,5 +1,30 @@ #!/bin/bash +KERBEROS=${KERBEROS-"false"} + +if [ $KERBEROS = "true" ]; then + echo prepare kerberos + ADMIN_PASSWORD="kerberos" + USER_PASSWORD="user" + + echo -e "$ADMIN_PASSWORD\n$ADMIN_PASSWORD" | kdb5_util -r "KERBEROS.RCLONE" create -s + echo -e "$ADMIN_PASSWORD\n$ADMIN_PASSWORD" | kadmin.local -q "addprinc hadoop/admin" + echo -e "$USER_PASSWORD\n$USER_PASSWORD" | kadmin.local -q "addprinc user" + kadmin.local -q 'addprinc -randkey hdfs/localhost' + kadmin.local -q 'addprinc -randkey hdfs/rclone-hdfs' + kadmin.local -q 'addprinc -randkey HTTP/localhost' + kadmin.local -p hadoop/admin -q "ktadd -k /etc/hadoop/kerberos.key hdfs/localhost hdfs/rclone-hdfs HTTP/localhost" + service krb5-kdc restart + echo -e "$USER_PASSWORD\n" | kinit user + klist + echo kerberos ready +else + echo drop kerberos from configuration files + sed -i '/KERBEROS BEGIN/,/KERBEROS END/d' /etc/hadoop/core-site.xml + sed -i '/KERBEROS BEGIN/,/KERBEROS END/d' /etc/hadoop/hdfs-site.xml +fi + + echo format namenode hdfs namenode -format test diff --git a/fstest/testserver/init.d/TestHdfs b/fstest/testserver/init.d/TestHdfs index 1c619e414..9860a7de7 100755 --- a/fstest/testserver/init.d/TestHdfs +++ b/fstest/testserver/init.d/TestHdfs @@ -3,19 +3,32 @@ set -e NAME=rclone-hdfs +KERBEROS=${KERBEROS-"false"} . $(dirname "$0")/docker.bash start() { - docker run --rm -d --name "rclone-hdfs" -p 127.0.0.1:9866:9866 -p 127.0.0.1:8020:8020 --hostname "rclone-hdfs" rclone/test-hdfs + docker run --rm -d --name "rclone-hdfs" \ + --hostname "rclone-hdfs" \ + -e "KERBEROS=$KERBEROS" \ + -p 127.0.0.1:9866:9866 \ + -p 127.0.0.1:8020:8020 \ + -p 127.0.0.1:750:750 \ + -p 127.0.0.1:88:88 \ + rclone/test-hdfs sleep 10 + if [ $KERBEROS = "true" ]; then + docker cp rclone-hdfs:/tmp/krb5cc_0 /tmp/krb5cc_`id -u` + fi + echo type=hdfs echo namenode=127.0.0.1:8020 echo username=root } stop() { if status ; then + docker logs $NAME > .stdout.log 2> .stderr.log docker kill $NAME echo "$NAME stopped" fi diff --git a/go.mod b/go.mod index 7e4d7e4fa..5a8b12a74 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( github.com/billziss-gh/cgofuse v1.4.0 github.com/buengese/sgzip v0.1.0 github.com/calebcase/tmpfile v1.0.2 // indirect - github.com/colinmarc/hdfs/v2 v2.1.1 + github.com/colinmarc/hdfs/v2 v2.2.0 github.com/coreos/go-semver v0.3.0 github.com/dropbox/dropbox-sdk-go-unofficial v5.6.0+incompatible github.com/gabriel-vasile/mimetype v1.1.1 @@ -26,6 +26,7 @@ require ( github.com/google/go-querystring v1.0.0 // indirect github.com/hanwen/go-fuse/v2 v2.0.3 github.com/iguanesolutions/go-systemd/v5 v5.0.0 + github.com/jcmturner/gokrb5/v8 v8.4.2 github.com/jlaffaye/ftp v0.0.0-20201112195030-9aae4d151126 github.com/jzelinskie/whirlpool v0.0.0-20201016144138-0675e54bb004 github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 // indirect @@ -57,7 +58,7 @@ require ( go.etcd.io/bbolt v1.3.5 go.uber.org/zap v1.16.0 // indirect goftp.io/server v0.4.0 - golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 + golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9 golang.org/x/net v0.0.0-20201029055024-942e2f445f3c golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 diff --git a/go.sum b/go.sum index f4207d7ff..ab4aedaf8 100644 --- a/go.sum +++ b/go.sum @@ -142,6 +142,8 @@ github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:z github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/colinmarc/hdfs/v2 v2.1.1 h1:x0hw/m+o3UE20Scso/KCkvYNc9Di39TBlCfGMkJ1/a0= github.com/colinmarc/hdfs/v2 v2.1.1/go.mod h1:M3x+k8UKKmxtFu++uAZ0OtDU8jR3jnaZIAc6yK4Ue0c= +github.com/colinmarc/hdfs/v2 v2.2.0 h1:4AaIlTq+/sWmeqYhI0dX8bD4YrMQM990tRjm636FkGM= +github.com/colinmarc/hdfs/v2 v2.2.0/go.mod h1:Wss6n3mtaZyRwWaqtSH+6ge01qT0rw9dJJmvoUnIQ/E= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= @@ -283,6 +285,9 @@ github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORR github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= +github.com/gorilla/sessions v1.2.0/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= +github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= @@ -310,6 +315,8 @@ github.com/hashicorp/go-uuid v0.0.0-20180228145832-27454136f036/go.mod h1:6SBZvO github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE= +github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= @@ -330,8 +337,24 @@ github.com/iguanesolutions/go-systemd/v5 v5.0.0/go.mod h1:VPlzL6z0rXd3HU7oLkMoEq github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= +github.com/jcmturner/aescts/v2 v2.0.0 h1:9YKLH6ey7H4eDBXW8khjYslgyqG2xZikXP0EQFKrle8= +github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs= +github.com/jcmturner/dnsutils/v2 v2.0.0 h1:lltnkeZGL0wILNvrNiVCR6Ro5PGU/SeBvVO/8c/iPbo= +github.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM= github.com/jcmturner/gofork v0.0.0-20180107083740-2aebee971930 h1:v4CYlQ+HeysPHsr2QFiEO60gKqnvn1xwvuKhhAhuEkk= github.com/jcmturner/gofork v0.0.0-20180107083740-2aebee971930/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o= +github.com/jcmturner/gofork v1.0.0 h1:J7uCkflzTEhUZ64xqKnkDxq3kzc96ajM1Gli5ktUem8= +github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o= +github.com/jcmturner/goidentity/v6 v6.0.1 h1:VKnZd2oEIMorCTsFBnJWbExfNN7yZr3EhJAxwOkZg6o= +github.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg= +github.com/jcmturner/gokrb5 v1.2.3 h1:cVAsP+5SqNm0HwYCokvDaGmxjQ7Q2i9gmq4jm6lHZpc= +github.com/jcmturner/gokrb5 v8.4.2+incompatible h1:MQW70Fbazv31g6URAXCjO2bGenIL0wVt3wqcpc0EjHI= +github.com/jcmturner/gokrb5/v8 v8.4.1/go.mod h1:T1hnNppQsBtxW0tCHMHTkAt8n/sABdzZgZdoFrZaZNM= +github.com/jcmturner/gokrb5/v8 v8.4.2 h1:6ZIM6b/JJN0X8UM43ZOM6Z4SJzla+a/u7scXFJzodkA= +github.com/jcmturner/gokrb5/v8 v8.4.2/go.mod h1:sb+Xq/fTY5yktf/VxLsE3wlfPqQjp0aWNYyvBVK62bc= +github.com/jcmturner/rpc/v2 v2.0.2/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc= +github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZY= +github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jlaffaye/ftp v0.0.0-20190624084859-c1312a7102bf/go.mod h1:lli8NYPQOFy3O++YmYbqVgOcQ1JPCwdOy+5zSjKJ9qY= github.com/jlaffaye/ftp v0.0.0-20201112195030-9aae4d151126 h1:ly2C51IMpCCV8RpTDRXgzG/L9iZXb8ePEixaew/HwBs= @@ -669,6 +692,7 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200117160349-530e935923ad/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -678,6 +702,8 @@ golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0 h1:hb9wdF1z5waM+dSIICn1l0 golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 h1:pLI5jrR7OSLijeIDcmRxNmw2api+jEfxLoykJVice/E= golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9 h1:umElSU9WZirRdgu2yFHY0ayQkEnKiOC1TtM3fWXFnoU= +golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=