check that the jwt token is used by the same IP for which it
Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
This commit is contained in:
parent
4bbb195711
commit
d955ddcef9
13 changed files with 154 additions and 118 deletions
2
.github/workflows/development.yml
vendored
2
.github/workflows/development.yml
vendored
|
@ -382,7 +382,7 @@ jobs:
|
|||
gzip output/man/man1/*
|
||||
cp sftpgo output/
|
||||
|
||||
- uses: uraimo/run-on-arch-action@v2.1.1
|
||||
- uses: uraimo/run-on-arch-action@v2
|
||||
if: ${{ matrix.arch != 'amd64' }}
|
||||
name: Build for ${{ matrix.arch }}
|
||||
id: build
|
||||
|
|
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
|
@ -326,7 +326,7 @@ jobs:
|
|||
env:
|
||||
SFTPGO_VERSION: ${{ steps.get_version.outputs.SFTPGO_VERSION }}
|
||||
|
||||
- uses: uraimo/run-on-arch-action@v2.1.1
|
||||
- uses: uraimo/run-on-arch-action@v2
|
||||
if: ${{ matrix.arch != 'amd64' }}
|
||||
name: Build for ${{ matrix.arch }}
|
||||
id: build
|
||||
|
|
|
@ -11,8 +11,6 @@ Several storage backends are supported: local filesystem, encrypted local filesy
|
|||
|
||||
## Features
|
||||
|
||||
<details>
|
||||
|
||||
- Support for serving local filesystem, encrypted local filesystem, S3 Compatible Object Storage, Google Cloud Storage, Azure Blob Storage or other SFTP accounts over SFTP/SCP/FTP/WebDAV.
|
||||
- Virtual folders are supported: a virtual folder can use any of the supported storage backends. So you can have, for example, an S3 user that exposes a GCS bucket (or part of it) on a specified path and an encrypted local filesystem on another one. Virtual folders can be private or shared among multiple users, for shared virtual folders you can define different quota limits for each user.
|
||||
- Configurable [custom commands and/or HTTP hooks](./docs/custom-actions.md) on file upload, pre-upload, download, pre-download, delete, pre-delete, rename, mkdir, rmdir on SSH commands and on user add, update and delete.
|
||||
|
@ -42,6 +40,7 @@ Several storage backends are supported: local filesystem, encrypted local filesy
|
|||
- Per-user and per-directory shell like patterns filters: files can be allowed, denied or hidden based on shell like patterns.
|
||||
- Automatically terminating idle connections.
|
||||
- Automatic blocklist management using the built-in [defender](./docs/defender.md).
|
||||
- Geo-IP filtering using a [plugin](https://github.com/sftpgo/sftpgo-plugin-geoipfilter).
|
||||
- Atomic uploads are configurable.
|
||||
- Per-user files/folders ownership mapping: you can map all the users to the system account that runs SFTPGo (all platforms are supported) or you can run SFTPGo as root user and map each user or group of users to a different system account (\*NIX only).
|
||||
- Support for Git repositories over SSH.
|
||||
|
@ -60,8 +59,6 @@ Several storage backends are supported: local filesystem, encrypted local filesy
|
|||
- Log files are accurate and they are saved in the easily parsable JSON format ([more information](./docs/logs.md)).
|
||||
- SFTPGo supports a [plugin system](./docs/plugins.md) and therefore can be extended using external plugins.
|
||||
|
||||
</details>
|
||||
|
||||
## Platforms
|
||||
|
||||
SFTPGo is developed and tested on Linux. After each commit, the code is automatically built and tested on Linux, macOS and Windows using a [GitHub Action](./.github/workflows/development.yml). The test cases are regularly manually executed and passed on FreeBSD. Other *BSD variants should work too.
|
||||
|
|
36
go.mod
36
go.mod
|
@ -8,12 +8,12 @@ require (
|
|||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.3.0
|
||||
github.com/GehirnInc/crypt v0.0.0-20200316065508-bb7000b8a962
|
||||
github.com/alexedwards/argon2id v0.0.0-20211130144151-3585854a6387
|
||||
github.com/aws/aws-sdk-go-v2 v1.16.0
|
||||
github.com/aws/aws-sdk-go-v2/config v1.15.1
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.11.0
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.1
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.26.1
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.16.1
|
||||
github.com/aws/aws-sdk-go-v2 v1.16.1
|
||||
github.com/aws/aws-sdk-go-v2/config v1.15.2
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.11.1
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.2
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.26.2
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.16.2
|
||||
github.com/cockroachdb/cockroach-go/v2 v2.2.8
|
||||
github.com/coreos/go-oidc/v3 v3.1.0
|
||||
github.com/eikenb/pipeat v0.0.0-20210730190139-06b3e6902001
|
||||
|
@ -75,17 +75,17 @@ require (
|
|||
cloud.google.com/go/compute v1.5.0 // indirect
|
||||
cloud.google.com/go/iam v0.3.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v0.9.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.7 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.8 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.11.1 // indirect
|
||||
github.com/aws/smithy-go v1.11.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.8 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.9 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.11.2 // indirect
|
||||
github.com/aws/smithy-go v1.11.2 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/boombuler/barcode v1.0.1 // indirect
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
|
||||
|
@ -147,7 +147,7 @@ require (
|
|||
golang.org/x/tools v0.1.10 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/genproto v0.0.0-20220323144105-ec3c684e5b14 // indirect
|
||||
google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb // indirect
|
||||
google.golang.org/grpc v1.45.0 // indirect
|
||||
google.golang.org/protobuf v1.28.0 // indirect
|
||||
gopkg.in/ini.v1 v1.66.4 // indirect
|
||||
|
|
72
go.sum
72
go.sum
|
@ -137,51 +137,51 @@ github.com/aws/aws-sdk-go v1.15.27/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZo
|
|||
github.com/aws/aws-sdk-go v1.37.0/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
|
||||
github.com/aws/aws-sdk-go v1.40.34/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q=
|
||||
github.com/aws/aws-sdk-go-v2 v1.9.0/go.mod h1:cK/D0BBs0b/oWPIcX/Z/obahJK1TT7IPVjy53i/mX/4=
|
||||
github.com/aws/aws-sdk-go-v2 v1.16.0 h1:cBAYjiiexRAg9v2z9vb6IdxAa7ef4KCtjW7w7e3GxGo=
|
||||
github.com/aws/aws-sdk-go-v2 v1.16.0/go.mod h1:lJYcuZZEHWNIb6ugJjbQY1fykdoobWbOS7kJYb4APoI=
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.0 h1:J/tiyHbl07LL4/1i0rFrW5pbLMvo7M6JrekBUNpLeT4=
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.0/go.mod h1:ohZjRmiToJ4NybwWTGOCbzlUQU8dxSHxYKzuX7k5l6Y=
|
||||
github.com/aws/aws-sdk-go-v2 v1.16.1 h1:udzee98w8H6ikRgtFdVN9JzzYEbi/quFfSvduZETJIU=
|
||||
github.com/aws/aws-sdk-go-v2 v1.16.1/go.mod h1:ytwTPBG6fXTZLxxeeCCWj2/EMYp/xDUgX+OET6TLNNU=
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.1 h1:SdK4Ppk5IzLs64ZMvr6MrSficMtjY2oS0WOORXTlxwU=
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.1/go.mod h1:n8Bs1ElDD2wJ9kCRTczA83gYbBmjSwZp3umc6zF4EeM=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.7.0/go.mod h1:w9+nMZ7soXCe5nT46Ri354SNhXDQ6v+V5wqDjnZE+GY=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.15.1 h1:hTIZFepYESYyowQUBo47lu69WSxsYqGUILY9Nu8+7pY=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.15.1/go.mod h1:MZHGbuW2WnqIOQQBKu2ZkhTjuutZSTnn56TDq4QyydE=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.15.2 h1:4oGcm1yqqtTc2Z8YpwehwjSiBA3TR0iZbFCgNlXcVFQ=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.15.2/go.mod h1:S1p1xf7DGVp0srNq0BakyxfirOldPQeDVlx7+fllyok=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.4.0/go.mod h1:dgGR+Qq7Wjcd4AOAW5Rf5Tnv3+x7ed6kETXyS9WCuAY=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.11.0 h1:gc4Uhs80s60nmLon5Z4JXWinX2BkAGT0YROoUT8h8U4=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.11.0/go.mod h1:EdV1ZFgtZ4XM5RDHWcRWK8H+xW5duNVBqWj2oLu7tRo=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.11.1 h1:uR323+M7ca3v2GKXbFSwWbNA3kLjjFzaalL6W4rpB9s=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.11.1/go.mod h1:pYrHWfKUoWTmbr+xTf6ZoWeyyvLAQ5BPT3aL+nKlTpE=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.5.0/go.mod h1:CpNzHK9VEFUCknu50kkB8z58AH2B5DvPP7ea1LHve/Y=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.1 h1:F9Je1nq5YXfMOv6451NHvMf6U0iTWeMnsG0MMIQoUmk=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.1/go.mod h1:Yph0XsTbQ5GGZ2+mO1a03P/SO9fdX3t1nejIp2tq79g=
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.1 h1:2lGuOytsLs4N2z1UmZ9s7BuhHMcZxNkm612YsLHK/8g=
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.1/go.mod h1:hkzjqerOQhhBGAL/DdmKLsP8hGZvtyvukCLvrU5twz4=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.7 h1:KUErSJgdqmqAPBWAp6Zx9CjL0YXfytXJeXcsWnuCM1c=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.7/go.mod h1:oB9nZcxH1cGq7NPGurVJwxrO2vmJ9mmEBayCwcAlmT8=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.1 h1:feVfa9eJonhJiss7g51ikjNB2DrUzbNZNvPL8pw/54k=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.1/go.mod h1:K4vz7lRYCyLYpYAMCLObODahFgARdD3YVa0MvQte9Co=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.2 h1:+AULPOLHEDjH2TcNKpixl4gt26hFOdlUuuisZUBFczA=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.2/go.mod h1:jmsqNRVo2XlUTNXG/NF7hM7o2gd2jhfg8vdJ135d4XA=
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.2 h1:PTFTblDWY/HdQ6ix5+to1uLARgLLuYbzKGLQnIdE5Us=
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.2/go.mod h1:j4OwU2Gb7yaQaidJRpdlIRYX93jBCWhVYIgMlPjf89o=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.8 h1:CDaO90VZVBAL1sK87S5oSPIrp7yZqORv1hPIi2UsTMk=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.8/go.mod h1:LnTQMTqbKsbtt+UI5+wPsB7jedW+2ZgozoPG8k6cMxg=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.2 h1:XXR3cdOcKRCTZf6ctcqpMf+go1BdzTm6+T9Ul5zxcMI=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.2/go.mod h1:1x4ZP3Z8odssdhuLI+/1Tqw6Pt/VAaP4Tr8EUxHvPXE=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.2.2/go.mod h1:BQV0agm+JEhqR+2RT5e1XTFIDcAAV0eW6z2trp+iduw=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.8 h1:adr3PfiggFtqgFofAMUFCtdvwzpf3QxPES4ezK4M3iI=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.8/go.mod h1:wLbQYt36AJqaRZUQiCNXzbtkNigyPfKHrotHuIDiCy8=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.0 h1:uhb7moM7VjqIEpWzTpCvceLDSwrWpaleXm39OnVjuLE=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.0/go.mod h1:pA2St3Pu2Ldy6fBPY45Azoh1WBG4oS7eIKOd4XN7Meg=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.1 h1:iq77O8kBduROlzJ6mhN8zqxXxctDZ1PnWY0kyCfYMGc=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.1/go.mod h1:1R7cjoiEG9cgMCBpIOuCyZWT0Dn87vNUeAaC8Reiaow=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.9 h1:8umg6LSQ/b0+ZTq+Ro8K7VLGVwd7kiYQtIACpf2N/Yo=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.9/go.mod h1:kASRBzoVW4I8KUmGCjsowAqVor9QU9DuTUABVducrTY=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.1 h1:T4pFel53bkHjL2mMo+4DKE6r6AuoZnM0fg7k1/ratr4=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.1/go.mod h1:GeUru+8VzrTXV/83XyMJ80KpH8xO89VPoUileyNQ+tc=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.2 h1:VoMBHtQZygRs8mcQNDrfmn09vFH2ccjf79nGJ0xuUfo=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.2/go.mod h1:2Fzbfwkx7z4yue1Lz6KDSKG84UpOcUKFl3VAtSF/gcg=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.3.0/go.mod h1:R1KK+vY8AfalhG1AOu5e35pOD2SdoPKQCFLTvnxiohk=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.1 h1:B/SPX7J+Y0Yrcjv60Nhbh1gC2uBN47SfN8JYre6Mp4M=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.1/go.mod h1:2Hhr9Eh1gJzDatwACX/ozAZ/ljq5vzvPRu5cdu25tzc=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.1 h1:sjASzLVAG9okVe5HgLur36itaOY4UC90VZNXAtcn0+s=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.1/go.mod h1:ELGakx1J1qEJqWkwiN0jh3CMDTN6v17kOgN8kZgo6LQ=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.2 h1:RrN7V0r8+lUUKZM4OAoCOIZqjPLZPOl6wuwMd2QIryI=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.2/go.mod h1:7hwSi01X5Yj9H0qLQljrn8OSdLwwSym1aQCfGn1tDQQ=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.2 h1:yxr9h06slG9fdVmO3CpBVuFVD73AeUHLmBxhCr3T3+E=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.2/go.mod h1:rvV/Jr4T8H3kMMw/9fFQw9kxqb70YKihA0oWuUFd3K8=
|
||||
github.com/aws/aws-sdk-go-v2/service/kms v1.5.0/go.mod h1:w7JuP9Oq1IKMFQPkNe3V6s9rOssXzOVEMNEqK1L1bao=
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.26.1 h1:FSoVdUKHxAzZKXuemm+7vVj3eOUY5u01SSwwkfhWpqA=
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.26.1/go.mod h1:ZS+sYP2DfetYS7n42MLAoz8x50T/w5su+rZmhaqTubg=
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.26.2 h1:Op/A+5+D1K0bmwH3BStYbp/7iod9Rdfm9898A0qYxLc=
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.26.2/go.mod h1:Ao1W746VIMdV1WhEkjeVa5JzlaE1JkxJ46facHX9kzs=
|
||||
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.6.0/go.mod h1:B+7C5UKdVq1ylkI/A6O8wcurFtaux0R1njePNPtKwoA=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssm v1.10.0/go.mod h1:4dXS5YNqI3SNbetQ7X7vfsMlX6ZnboJA2dulBwJx7+g=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.4.0/go.mod h1:+1fpWnL96DL23aXPpMGbsmKe8jLTEfbjuQoA4WS1VaA=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.11.1 h1:DyHctRsJIAWIvom1Itb4T84D2jwpIu+KIi3d0SFaswg=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.11.1/go.mod h1:CvFTucADIx7U/M44vjLs/ZttpQHdpxwK+62+dUGhDeY=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.11.2 h1:8fVz1c9B/63w7O0kxbrCTT69iV4DgXnFumarPCZ3Cns=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.11.2/go.mod h1:GdCj3+FzI3D5tauOzz8n3YjN70XvgZz82PVVtJXmDds=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.7.0/go.mod h1:0qcSMCyASQPN2sk/1KQLQ2Fh6yq8wm0HSDAimPhzCoM=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.16.1 h1:xsOtPAvHqhvQvBza5ohaUcfq1LceH2lZKMUGZJKiZiM=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.16.1/go.mod h1:Aq2/Qggh2oemSfyHH+EO4UBbgWG6zFCXLHYI4ILTY7w=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.16.2 h1:qgK5htfKByTiPxS/diZ/mTCfDwGAVuyjRdqu6VoCh80=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.16.2/go.mod h1:RoMljzynmRe3jyOsRgqIMTzyhpAv6XNxu549M1X4Mdo=
|
||||
github.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E=
|
||||
github.com/aws/smithy-go v1.11.1 h1:IQ+lPZVkSM3FRtyaDox41R8YS6iwPMYIreejOgPW49g=
|
||||
github.com/aws/smithy-go v1.11.1/go.mod h1:3xHYmszWVx2c0kIwQeEVf9uSm4fYZt67FBJnwub1bgM=
|
||||
github.com/aws/smithy-go v1.11.2 h1:eG/N+CcUMAvsdffgMvjMKwfyDzIkjM6pfxMJ8Mzc6mE=
|
||||
github.com/aws/smithy-go v1.11.2/go.mod h1:3xHYmszWVx2c0kIwQeEVf9uSm4fYZt67FBJnwub1bgM=
|
||||
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
|
@ -1131,8 +1131,8 @@ google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2
|
|||
google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
|
||||
google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
|
||||
google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
|
||||
google.golang.org/genproto v0.0.0-20220323144105-ec3c684e5b14 h1:17TOyVD+9MLIDtDJW9PdtMuVT7gNLEkN+G/xFYjZmr8=
|
||||
google.golang.org/genproto v0.0.0-20220323144105-ec3c684e5b14/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E=
|
||||
google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb h1:0m9wktIpOxGw+SSKmydXWB3Z3GTfcPP6+q75HCQa6HI=
|
||||
google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E=
|
||||
google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
|
|
|
@ -159,11 +159,11 @@ func (c *jwtTokenClaims) hasPerm(perm string) bool {
|
|||
return util.IsStringInSlice(perm, c.Permissions)
|
||||
}
|
||||
|
||||
func (c *jwtTokenClaims) createToken(tokenAuth *jwtauth.JWTAuth, audience tokenAudience) (jwt.Token, string, error) {
|
||||
func (c *jwtTokenClaims) createToken(tokenAuth *jwtauth.JWTAuth, audience tokenAudience, ip string) (jwt.Token, string, error) {
|
||||
claims := c.asMap()
|
||||
now := time.Now().UTC()
|
||||
|
||||
claims[jwt.JwtIDKey] = xid.New().String()
|
||||
claims[jwt.JwtIDKey] = fmt.Sprintf("%s%s", xid.New().String(), ip)
|
||||
claims[jwt.NotBeforeKey] = now.Add(-30 * time.Second)
|
||||
claims[jwt.ExpirationKey] = now.Add(tokenDuration)
|
||||
claims[jwt.AudienceKey] = audience
|
||||
|
@ -171,8 +171,8 @@ func (c *jwtTokenClaims) createToken(tokenAuth *jwtauth.JWTAuth, audience tokenA
|
|||
return tokenAuth.Encode(claims)
|
||||
}
|
||||
|
||||
func (c *jwtTokenClaims) createTokenResponse(tokenAuth *jwtauth.JWTAuth, audience tokenAudience) (map[string]interface{}, error) {
|
||||
token, tokenString, err := c.createToken(tokenAuth, audience)
|
||||
func (c *jwtTokenClaims) createTokenResponse(tokenAuth *jwtauth.JWTAuth, audience tokenAudience, ip string) (map[string]interface{}, error) {
|
||||
token, tokenString, err := c.createToken(tokenAuth, audience, ip)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -184,8 +184,10 @@ func (c *jwtTokenClaims) createTokenResponse(tokenAuth *jwtauth.JWTAuth, audienc
|
|||
return response, nil
|
||||
}
|
||||
|
||||
func (c *jwtTokenClaims) createAndSetCookie(w http.ResponseWriter, r *http.Request, tokenAuth *jwtauth.JWTAuth, audience tokenAudience) error {
|
||||
resp, err := c.createTokenResponse(tokenAuth, audience)
|
||||
func (c *jwtTokenClaims) createAndSetCookie(w http.ResponseWriter, r *http.Request, tokenAuth *jwtauth.JWTAuth,
|
||||
audience tokenAudience, ip string,
|
||||
) error {
|
||||
resp, err := c.createTokenResponse(tokenAuth, audience, ip)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -8713,6 +8713,38 @@ func TestWebClientMaxConnections(t *testing.T) {
|
|||
common.Config.MaxTotalConnections = oldValue
|
||||
}
|
||||
|
||||
func TestTokenInvalidIPAddress(t *testing.T) {
|
||||
user, _, err := httpdtest.AddUser(getTestUser(), http.StatusCreated)
|
||||
assert.NoError(t, err)
|
||||
|
||||
webToken, err := getJWTWebClientTokenFromTestServerWithAddr(defaultUsername, defaultPassword, "1.1.1.1")
|
||||
assert.NoError(t, err)
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, webClientFilesPath, nil)
|
||||
assert.NoError(t, err)
|
||||
req.RemoteAddr = "1.1.1.2"
|
||||
req.RequestURI = webClientFilesPath
|
||||
setJWTCookieForReq(req, webToken)
|
||||
rr := executeRequest(req)
|
||||
checkResponseCode(t, http.StatusFound, rr)
|
||||
|
||||
apiToken, err := getJWTAPIUserTokenFromTestServer(defaultUsername, defaultPassword)
|
||||
assert.NoError(t, err)
|
||||
|
||||
req, err = http.NewRequest(http.MethodGet, userDirsPath+"/?path=%2F", nil)
|
||||
assert.NoError(t, err)
|
||||
req.RemoteAddr = "2.2.2.2"
|
||||
setBearerForReq(req, apiToken)
|
||||
rr = executeRequest(req)
|
||||
checkResponseCode(t, http.StatusUnauthorized, rr)
|
||||
assert.Contains(t, rr.Body.String(), "Your token is not valid")
|
||||
|
||||
_, err = httpdtest.RemoveUser(user, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
err = os.RemoveAll(user.GetHomeDir())
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestDefender(t *testing.T) {
|
||||
oldConfig := config.GetCommonConfig()
|
||||
|
||||
|
@ -17500,7 +17532,7 @@ func getJWTAPIUserTokenFromTestServer(username, password string) (string, error)
|
|||
req.SetBasicAuth(username, password)
|
||||
rr := executeRequest(req)
|
||||
if rr.Code != http.StatusOK {
|
||||
return "", fmt.Errorf("unexpected status code %v", rr.Code)
|
||||
return "", fmt.Errorf("unexpected status code %v", rr.Code)
|
||||
}
|
||||
responseHolder := make(map[string]interface{})
|
||||
err := render.DecodeJSON(rr.Body, &responseHolder)
|
||||
|
|
|
@ -629,7 +629,7 @@ func TestUpdateWebAdminInvalidClaims(t *testing.T) {
|
|||
Permissions: admin.Permissions,
|
||||
Signature: admin.GetSignature(),
|
||||
}
|
||||
token, err := c.createTokenResponse(server.tokenAuth, tokenAudienceWebAdmin)
|
||||
token, err := c.createTokenResponse(server.tokenAuth, tokenAudienceWebAdmin, "")
|
||||
assert.NoError(t, err)
|
||||
|
||||
form := make(url.Values)
|
||||
|
@ -746,7 +746,7 @@ func TestCreateTokenError(t *testing.T) {
|
|||
}
|
||||
req, _ := http.NewRequest(http.MethodGet, tokenPath, nil)
|
||||
|
||||
server.generateAndSendToken(rr, req, admin)
|
||||
server.generateAndSendToken(rr, req, admin, "")
|
||||
assert.Equal(t, http.StatusInternalServerError, rr.Code)
|
||||
|
||||
rr = httptest.NewRecorder()
|
||||
|
@ -778,7 +778,7 @@ func TestCreateTokenError(t *testing.T) {
|
|||
assert.Equal(t, http.StatusOK, rr.Code, rr.Body.String())
|
||||
req, _ = http.NewRequest(http.MethodPost, webAdminSetupPath, nil)
|
||||
rr = httptest.NewRecorder()
|
||||
server.loginAdmin(rr, req, &admin, false, nil)
|
||||
server.loginAdmin(rr, req, &admin, false, nil, "")
|
||||
// req with no POST body
|
||||
req, _ = http.NewRequest(http.MethodGet, webAdminLoginPath+"?a=a%C3%AO%GG", nil)
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
|
@ -1991,7 +1991,7 @@ func TestWebUserInvalidClaims(t *testing.T) {
|
|||
Permissions: nil,
|
||||
Signature: user.GetSignature(),
|
||||
}
|
||||
token, err := c.createTokenResponse(server.tokenAuth, tokenAudienceWebClient)
|
||||
token, err := c.createTokenResponse(server.tokenAuth, tokenAudienceWebClient, "")
|
||||
assert.NoError(t, err)
|
||||
|
||||
req, _ := http.NewRequest(http.MethodGet, webClientFilesPath, nil)
|
||||
|
@ -2066,7 +2066,7 @@ func TestInvalidClaims(t *testing.T) {
|
|||
Permissions: nil,
|
||||
Signature: user.GetSignature(),
|
||||
}
|
||||
token, err := c.createTokenResponse(server.tokenAuth, tokenAudienceWebClient)
|
||||
token, err := c.createTokenResponse(server.tokenAuth, tokenAudienceWebClient, "")
|
||||
assert.NoError(t, err)
|
||||
form := make(url.Values)
|
||||
form.Set(csrfFormToken, createCSRFToken())
|
||||
|
@ -2086,7 +2086,7 @@ func TestInvalidClaims(t *testing.T) {
|
|||
Permissions: nil,
|
||||
Signature: admin.GetSignature(),
|
||||
}
|
||||
token, err = c.createTokenResponse(server.tokenAuth, tokenAudienceWebAdmin)
|
||||
token, err = c.createTokenResponse(server.tokenAuth, tokenAudienceWebAdmin, "")
|
||||
assert.NoError(t, err)
|
||||
form = make(url.Values)
|
||||
form.Set(csrfFormToken, createCSRFToken())
|
||||
|
@ -2134,7 +2134,7 @@ func TestSigningKey(t *testing.T) {
|
|||
Permissions: nil,
|
||||
Signature: user.GetSignature(),
|
||||
}
|
||||
token, err := c.createTokenResponse(server1.tokenAuth, tokenAudienceWebClient)
|
||||
token, err := c.createTokenResponse(server1.tokenAuth, tokenAudienceWebClient, "")
|
||||
assert.NoError(t, err)
|
||||
accessToken := token["access_token"].(string)
|
||||
assert.NotEmpty(t, accessToken)
|
||||
|
|
|
@ -42,33 +42,29 @@ func validateJWTToken(w http.ResponseWriter, r *http.Request, audience tokenAudi
|
|||
|
||||
isAPIToken := (audience == tokenAudienceAPI || audience == tokenAudienceAPIUser)
|
||||
|
||||
if err != nil || token == nil {
|
||||
logger.Debug(logSender, "", "error getting jwt token: %v", err)
|
||||
doRedirect := func(message string, err error) {
|
||||
if isAPIToken {
|
||||
sendAPIResponse(w, r, err, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
|
||||
sendAPIResponse(w, r, err, message, http.StatusUnauthorized)
|
||||
} else {
|
||||
http.Redirect(w, r, redirectPath, http.StatusFound)
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil || token == nil {
|
||||
logger.Debug(logSender, "", "error getting jwt token: %v", err)
|
||||
doRedirect(http.StatusText(http.StatusUnauthorized), err)
|
||||
return errInvalidToken
|
||||
}
|
||||
|
||||
err = jwt.Validate(token)
|
||||
if err != nil {
|
||||
logger.Debug(logSender, "", "error validating jwt token: %v", err)
|
||||
if isAPIToken {
|
||||
sendAPIResponse(w, r, err, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
|
||||
} else {
|
||||
http.Redirect(w, r, redirectPath, http.StatusFound)
|
||||
}
|
||||
doRedirect(http.StatusText(http.StatusUnauthorized), err)
|
||||
return errInvalidToken
|
||||
}
|
||||
if isTokenInvalidated(r) {
|
||||
logger.Debug(logSender, "", "the token has been invalidated")
|
||||
if isAPIToken {
|
||||
sendAPIResponse(w, r, nil, "Your token is no longer valid", http.StatusUnauthorized)
|
||||
} else {
|
||||
http.Redirect(w, r, redirectPath, http.StatusFound)
|
||||
}
|
||||
doRedirect("Your token is no longer valid", nil)
|
||||
return errInvalidToken
|
||||
}
|
||||
// a user with a partial token will be always redirected to the appropriate two factor auth page
|
||||
|
@ -77,11 +73,13 @@ func validateJWTToken(w http.ResponseWriter, r *http.Request, audience tokenAudi
|
|||
}
|
||||
if !util.IsStringInSlice(audience, token.Audience()) {
|
||||
logger.Debug(logSender, "", "the token is not valid for audience %#v", audience)
|
||||
if isAPIToken {
|
||||
sendAPIResponse(w, r, nil, "Your token audience is not valid", http.StatusUnauthorized)
|
||||
} else {
|
||||
http.Redirect(w, r, redirectPath, http.StatusFound)
|
||||
}
|
||||
doRedirect("Your token audience is not valid", nil)
|
||||
return errInvalidToken
|
||||
}
|
||||
ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
|
||||
if ipAddr != "" && !strings.Contains(token.JwtID(), ipAddr) {
|
||||
logger.Debug(logSender, "", "the token with id %#v is not valid for the ip address %#v", token.JwtID(), ipAddr)
|
||||
doRedirect("Your token is not valid", nil)
|
||||
return errInvalidToken
|
||||
}
|
||||
return nil
|
||||
|
@ -382,7 +380,8 @@ func authenticateAdminWithAPIKey(username, keyID string, tokenAuth *jwtauth.JWTA
|
|||
if !admin.Filters.AllowAPIKeyAuth {
|
||||
return fmt.Errorf("API key authentication disabled for admin %#v", admin.Username)
|
||||
}
|
||||
if err := admin.CanLogin(util.GetIPFromRemoteAddress(r.RemoteAddr)); err != nil {
|
||||
ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
|
||||
if err := admin.CanLogin(ipAddr); err != nil {
|
||||
return err
|
||||
}
|
||||
c := jwtTokenClaims{
|
||||
|
@ -392,7 +391,7 @@ func authenticateAdminWithAPIKey(username, keyID string, tokenAuth *jwtauth.JWTA
|
|||
APIKeyID: keyID,
|
||||
}
|
||||
|
||||
resp, err := c.createTokenResponse(tokenAuth, tokenAudienceAPI)
|
||||
resp, err := c.createTokenResponse(tokenAuth, tokenAudienceAPI, ipAddr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -446,7 +445,7 @@ func authenticateUserWithAPIKey(username, keyID string, tokenAuth *jwtauth.JWTAu
|
|||
APIKeyID: keyID,
|
||||
}
|
||||
|
||||
resp, err := c.createTokenResponse(tokenAuth, tokenAudienceAPIUser)
|
||||
resp, err := c.createTokenResponse(tokenAuth, tokenAudienceAPIUser, ipAddr)
|
||||
if err != nil {
|
||||
updateLoginMetrics(&user, dataprovider.LoginMethodPassword, ipAddr, common.ErrInternalFailure)
|
||||
return err
|
||||
|
|
|
@ -496,7 +496,7 @@ func (s *httpdServer) oidcTokenAuthenticator(audience tokenAudience) func(next h
|
|||
Username: token.Username,
|
||||
Permissions: token.Permissions,
|
||||
}
|
||||
_, tokenString, err := jwtTokenClaims.createToken(s.tokenAuth, audience)
|
||||
_, tokenString, err := jwtTokenClaims.createToken(s.tokenAuth, audience, util.GetIPFromRemoteAddress(r.RemoteAddr))
|
||||
if err != nil {
|
||||
setFlashMessage(w, r, "Unable to create cookie")
|
||||
if audience == tokenAudienceWebAdmin {
|
||||
|
|
|
@ -666,7 +666,7 @@ func TestSkipOIDCAuth(t *testing.T) {
|
|||
jwtTokenClaims := jwtTokenClaims{
|
||||
Username: "user",
|
||||
}
|
||||
_, tokenString, err := jwtTokenClaims.createToken(server.tokenAuth, tokenAudienceWebClient)
|
||||
_, tokenString, err := jwtTokenClaims.createToken(server.tokenAuth, tokenAudienceWebClient, "")
|
||||
assert.NoError(t, err)
|
||||
rr := httptest.NewRecorder()
|
||||
r, err := http.NewRequest(http.MethodGet, webClientLogoutPath, nil)
|
||||
|
|
|
@ -413,6 +413,7 @@ func (s *httpdServer) handleWebAdminTwoFactorRecoveryPost(w http.ResponseWriter,
|
|||
s.renderTwoFactorRecoveryPage(w, "Two factory authentication is not enabled")
|
||||
return
|
||||
}
|
||||
ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
|
||||
for idx, code := range admin.Filters.RecoveryCodes {
|
||||
if err := code.Secret.Decrypt(); err != nil {
|
||||
s.renderInternalServerErrorPage(w, r, fmt.Errorf("unable to decrypt recovery code: %w", err))
|
||||
|
@ -424,13 +425,13 @@ func (s *httpdServer) handleWebAdminTwoFactorRecoveryPost(w http.ResponseWriter,
|
|||
return
|
||||
}
|
||||
admin.Filters.RecoveryCodes[idx].Used = true
|
||||
err = dataprovider.UpdateAdmin(&admin, dataprovider.ActionExecutorSelf, util.GetIPFromRemoteAddress(r.RemoteAddr))
|
||||
err = dataprovider.UpdateAdmin(&admin, dataprovider.ActionExecutorSelf, ipAddr)
|
||||
if err != nil {
|
||||
logger.Warn(logSender, "", "unable to set the recovery code %#v as used: %v", recoveryCode, err)
|
||||
s.renderInternalServerErrorPage(w, r, errors.New("unable to set the recovery code as used"))
|
||||
return
|
||||
}
|
||||
s.loginAdmin(w, r, &admin, true, s.renderTwoFactorRecoveryPage)
|
||||
s.loginAdmin(w, r, &admin, true, s.renderTwoFactorRecoveryPage, ipAddr)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -478,7 +479,7 @@ func (s *httpdServer) handleWebAdminTwoFactorPost(w http.ResponseWriter, r *http
|
|||
s.renderTwoFactorPage(w, "Invalid authentication code")
|
||||
return
|
||||
}
|
||||
s.loginAdmin(w, r, &admin, true, s.renderTwoFactorPage)
|
||||
s.loginAdmin(w, r, &admin, true, s.renderTwoFactorPage, util.GetIPFromRemoteAddress(r.RemoteAddr))
|
||||
}
|
||||
|
||||
func (s *httpdServer) handleWebAdminLoginPost(w http.ResponseWriter, r *http.Request) {
|
||||
|
@ -497,12 +498,13 @@ func (s *httpdServer) handleWebAdminLoginPost(w http.ResponseWriter, r *http.Req
|
|||
s.renderAdminLoginPage(w, err.Error())
|
||||
return
|
||||
}
|
||||
admin, err := dataprovider.CheckAdminAndPass(username, password, util.GetIPFromRemoteAddress(r.RemoteAddr))
|
||||
ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
|
||||
admin, err := dataprovider.CheckAdminAndPass(username, password, ipAddr)
|
||||
if err != nil {
|
||||
s.renderAdminLoginPage(w, err.Error())
|
||||
return
|
||||
}
|
||||
s.loginAdmin(w, r, &admin, false, s.renderAdminLoginPage)
|
||||
s.loginAdmin(w, r, &admin, false, s.renderAdminLoginPage, ipAddr)
|
||||
}
|
||||
|
||||
func (s *httpdServer) renderAdminLoginPage(w http.ResponseWriter, error string) {
|
||||
|
@ -585,7 +587,7 @@ func (s *httpdServer) handleWebAdminPasswordResetPost(w http.ResponseWriter, r *
|
|||
return
|
||||
}
|
||||
|
||||
s.loginAdmin(w, r, admin, false, s.renderResetPwdPage)
|
||||
s.loginAdmin(w, r, admin, false, s.renderResetPwdPage, util.GetIPFromRemoteAddress(r.RemoteAddr))
|
||||
}
|
||||
|
||||
func (s *httpdServer) handleWebAdminSetupPost(w http.ResponseWriter, r *http.Request) {
|
||||
|
@ -629,12 +631,13 @@ func (s *httpdServer) handleWebAdminSetupPost(w http.ResponseWriter, r *http.Req
|
|||
Status: 1,
|
||||
Permissions: []string{dataprovider.PermAdminAny},
|
||||
}
|
||||
err = dataprovider.AddAdmin(&admin, username, util.GetIPFromRemoteAddress(r.RemoteAddr))
|
||||
ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
|
||||
err = dataprovider.AddAdmin(&admin, username, ipAddr)
|
||||
if err != nil {
|
||||
s.renderAdminSetupPage(w, r, username, err.Error())
|
||||
return
|
||||
}
|
||||
s.loginAdmin(w, r, &admin, false, nil)
|
||||
s.loginAdmin(w, r, &admin, false, nil, ipAddr)
|
||||
}
|
||||
|
||||
func (s *httpdServer) loginUser(
|
||||
|
@ -655,7 +658,7 @@ func (s *httpdServer) loginUser(
|
|||
audience = tokenAudienceWebClientPartial
|
||||
}
|
||||
|
||||
err := c.createAndSetCookie(w, r, s.tokenAuth, audience)
|
||||
err := c.createAndSetCookie(w, r, s.tokenAuth, audience, ipAddr)
|
||||
if err != nil {
|
||||
logger.Warn(logSender, connectionID, "unable to set user login cookie %v", err)
|
||||
updateLoginMetrics(user, dataprovider.LoginMethodPassword, ipAddr, common.ErrInternalFailure)
|
||||
|
@ -676,7 +679,7 @@ func (s *httpdServer) loginUser(
|
|||
|
||||
func (s *httpdServer) loginAdmin(
|
||||
w http.ResponseWriter, r *http.Request, admin *dataprovider.Admin,
|
||||
isSecondFactorAuth bool, errorFunc func(w http.ResponseWriter, error string),
|
||||
isSecondFactorAuth bool, errorFunc func(w http.ResponseWriter, error string), ip string,
|
||||
) {
|
||||
c := jwtTokenClaims{
|
||||
Username: admin.Username,
|
||||
|
@ -689,7 +692,7 @@ func (s *httpdServer) loginAdmin(
|
|||
audience = tokenAudienceWebAdminPartial
|
||||
}
|
||||
|
||||
err := c.createAndSetCookie(w, r, s.tokenAuth, audience)
|
||||
err := c.createAndSetCookie(w, r, s.tokenAuth, audience, ip)
|
||||
if err != nil {
|
||||
logger.Warn(logSender, "", "unable to set admin login cookie %v", err)
|
||||
if errorFunc == nil {
|
||||
|
@ -803,7 +806,7 @@ func (s *httpdServer) generateAndSendUserToken(w http.ResponseWriter, r *http.Re
|
|||
RequiredTwoFactorProtocols: user.Filters.TwoFactorAuthProtocols,
|
||||
}
|
||||
|
||||
resp, err := c.createTokenResponse(s.tokenAuth, tokenAudienceAPIUser)
|
||||
resp, err := c.createTokenResponse(s.tokenAuth, tokenAudienceAPIUser, ipAddr)
|
||||
|
||||
if err != nil {
|
||||
updateLoginMetrics(&user, dataprovider.LoginMethodPassword, ipAddr, common.ErrInternalFailure)
|
||||
|
@ -823,7 +826,8 @@ func (s *httpdServer) getToken(w http.ResponseWriter, r *http.Request) {
|
|||
sendAPIResponse(w, r, nil, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
admin, err := dataprovider.CheckAdminAndPass(username, password, util.GetIPFromRemoteAddress(r.RemoteAddr))
|
||||
ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
|
||||
admin, err := dataprovider.CheckAdminAndPass(username, password, ipAddr)
|
||||
if err != nil {
|
||||
w.Header().Set(common.HTTPAuthenticationHeader, basicRealm)
|
||||
sendAPIResponse(w, r, err, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
|
||||
|
@ -854,17 +858,17 @@ func (s *httpdServer) getToken(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
}
|
||||
|
||||
s.generateAndSendToken(w, r, admin)
|
||||
s.generateAndSendToken(w, r, admin, ipAddr)
|
||||
}
|
||||
|
||||
func (s *httpdServer) generateAndSendToken(w http.ResponseWriter, r *http.Request, admin dataprovider.Admin) {
|
||||
func (s *httpdServer) generateAndSendToken(w http.ResponseWriter, r *http.Request, admin dataprovider.Admin, ip string) {
|
||||
c := jwtTokenClaims{
|
||||
Username: admin.Username,
|
||||
Permissions: admin.Permissions,
|
||||
Signature: admin.GetSignature(),
|
||||
}
|
||||
|
||||
resp, err := c.createTokenResponse(s.tokenAuth, tokenAudienceAPI)
|
||||
resp, err := c.createTokenResponse(s.tokenAuth, tokenAudienceAPI, ip)
|
||||
|
||||
if err != nil {
|
||||
sendAPIResponse(w, r, err, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||
|
@ -914,7 +918,7 @@ func (s *httpdServer) refreshClientToken(w http.ResponseWriter, r *http.Request,
|
|||
|
||||
tokenClaims.Permissions = user.Filters.WebClient
|
||||
logger.Debug(logSender, "", "cookie refreshed for user %#v", user.Username)
|
||||
tokenClaims.createAndSetCookie(w, r, s.tokenAuth, tokenAudienceWebClient) //nolint:errcheck
|
||||
tokenClaims.createAndSetCookie(w, r, s.tokenAuth, tokenAudienceWebClient, util.GetIPFromRemoteAddress(r.RemoteAddr)) //nolint:errcheck
|
||||
}
|
||||
|
||||
func (s *httpdServer) refreshAdminToken(w http.ResponseWriter, r *http.Request, tokenClaims jwtTokenClaims) {
|
||||
|
@ -930,13 +934,14 @@ func (s *httpdServer) refreshAdminToken(w http.ResponseWriter, r *http.Request,
|
|||
logger.Debug(logSender, "", "signature mismatch for admin %#v, unable to refresh cookie", admin.Username)
|
||||
return
|
||||
}
|
||||
if !admin.CanLoginFromIP(util.GetIPFromRemoteAddress(r.RemoteAddr)) {
|
||||
ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
|
||||
if !admin.CanLoginFromIP(ipAddr) {
|
||||
logger.Debug(logSender, "", "admin %#v cannot login from %v, unable to refresh cookie", admin.Username, r.RemoteAddr)
|
||||
return
|
||||
}
|
||||
tokenClaims.Permissions = admin.Permissions
|
||||
logger.Debug(logSender, "", "cookie refreshed for admin %#v", admin.Username)
|
||||
tokenClaims.createAndSetCookie(w, r, s.tokenAuth, tokenAudienceWebAdmin) //nolint:errcheck
|
||||
tokenClaims.createAndSetCookie(w, r, s.tokenAuth, tokenAudienceWebAdmin, ipAddr) //nolint:errcheck
|
||||
}
|
||||
|
||||
func (s *httpdServer) updateContextFromCookie(r *http.Request) *http.Request {
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"bytes"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
|
@ -509,7 +510,7 @@ func (c *Configuration) AcceptInboundConnection(conn net.Conn, config *ssh.Serve
|
|||
go func(in <-chan *ssh.Request, counter int64) {
|
||||
for req := range in {
|
||||
ok := false
|
||||
connID := fmt.Sprintf("%v_%v", connectionID, counter)
|
||||
connID := fmt.Sprintf("%s_%d", connectionID, counter)
|
||||
|
||||
switch req.Type {
|
||||
case "subsystem":
|
||||
|
@ -879,7 +880,7 @@ func (c *Configuration) validatePublicKeyCredentials(conn ssh.ConnMetadata, pubK
|
|||
return nil, err
|
||||
}
|
||||
if !c.certChecker.IsUserAuthority(cert.SignatureKey) {
|
||||
err = fmt.Errorf("ssh: certificate signed by unrecognized authority")
|
||||
err = errors.New("ssh: certificate signed by unrecognized authority")
|
||||
user.Username = conn.User()
|
||||
updateLoginMetrics(&user, ipAddr, method, err)
|
||||
return nil, err
|
||||
|
|
Loading…
Reference in a new issue