GithubHelp home page GithubHelp logo

cloudposse / bastion Goto Github PK

View Code? Open in Web Editor NEW
635.0 36.0 112.0 305 KB

🔒Secure Bastion implemented as Docker Container running Alpine Linux with Google Authenticator & DUO MFA support

Home Page: https://cloudposse.com/accelerate

License: Apache License 2.0

Makefile 6.13% Shell 73.09% Dockerfile 20.78%
bastion docker dockerfile alpine linux openssh mfa duo google-authenticator slack

bastion's Introduction

bastion Latest Release Build & Test Status Slack Community

README Header

Cloud Posse

This is a secure/locked-down bastion implemented as a Docker Container. It uses Alpine Linux as the base image and ships with support for Google Authenticator & DUO MFA support.

It was designed to be used on Kubernetes together with GitHub Authorized Keys to provide secure remote access to production clusters.

MFA Setup & Usage

Here's a demo of what a user experiences when setting up Google Authenticator for the first time.

Demo 1

When using Duo as the MFA provider, this becomes even more magical because Duo supports automatic Push notifications to your mobile device. Just approve the request on your mobile phone (e.g. with a thumb press on iOS) when prompted.

Slack Notifications

Here's what it looks like when someone connects to the bastion if Slack notifications are enabled.

Demo 2

We recommend using Slack notifications for self-reporting.

  • Any time a user accesses production systems, they should reply to the slack notification to justify their remote access.
  • A "buddy" should approve the login by adding a reaction (e.g. ✅).
  • If no one approves the login, it should trigger an incident response to track down the unauthorized access.

This project is part of our comprehensive "SweetOps" approach towards DevOps.

It's 100% Open Source and licensed under the APACHE2.

Usage

Running

Refer to the Environment Variables section below to tune how the bastion operates.

$ docker run -p 1234:22 cloudposse/bastion:latest

Building

$ git clone https://github.com/cloudposse/bastion.git
$ cd bastion
$ make docker:build

Testing

Run basic connection tests

$ make test

Configuration

Recommendations

  • Do not allow root (or sudo) access to this container as doing so would allow remote users to manipulate audit-logs in /var/log/sudo-io
  • Use the bastion as a "jump host" for accessing other internal systems rather than installing a lot of unnecessary stuff, which increases the overall attack surface.
  • Sync the contents of /var/log/sudo-io to a remote, offsite location. If using S3, we recommend enabling bucket-versioning.
  • Use `github-authorized-keys to automatically provision users; or use the Helm chart.
  • Bind-mount /etc/passwd, /etc/shadow and /etc/group into the container as read-only
  • Bind-mount /home into container; the bastion does not manage authorized keys

Environment Variables

The following tables lists the most relevant environment variables of the bastion image and their default values.

Duo Settings

Duo is a enterprise MFA provider that is very affordable. Details here: https://duo.com/pricing

ENV Description Default
MFA_PROVIDER Enable the Duo MFA provider duo
DUO_IKEY Duo Integration Key
DUO_SKEY Duo Secret Key
DUO_HOST Duo Host Endpoint
DUO_FAILMODE How to fail if Duo cannot be reached secure
DUO_AUTOPUSH Automatically send a push notification yes
DUO_PROMPTS How many times to prompt for MFA 1
Google Authenticator Settings

Google Authenticator is a free & open source MFA solution. It's less secure than Duo because tokens are stored on the server under each user account.

ENV Description Default
MFA_PROVIDER Enable the Google Authenticator provider google-authenticator
Enforcer Settings

The enforcer ensures certain conditions are satisfied. Currently, these options are supported.

ENV Description Default
ENFORCER_ENABLED Enable general enforcement true
ENFORCER_CLEAN_HOME_ENABLED Erase dot files in home directory before starting session true
Slack Notifications

The enforcer is able to send notifications to a slack channel anytime there is an SSH login.

ENV Description Default
SLACK_ENABLED Enabled Slack integration false
SLACK_HOOK Slack integration method (e.g. pam, sshrc) sshrc
SLACK_WEBHOOK_URL Webhook URL
SLACK_USERNAME Slack handle of bot (defaults to short-dns name)
SLACK_TIMEOUT Request timeout 2
SLACK_FATAL_ERRORS Deny logins if slack notification fails true
SSH Auditor

The SSH auditor uses sudosh to record entire SSH sessions (stdin, stdout, and stderr).

ENV Description Default
SSH_AUDIT_ENABLED Enable the SSH Audit facility true

This will require that users login with the /usr/bin/sudosh shell.

Update user's default shell by running the command: usermod -s /usr/bin/sudosh $username. By default, root will automatically be updated to use sudosh.

Use the sudoreplay command to audit/replay sessions.

User Accounts & SSH Keys

The bastion does not attempt to manage user accounts. We suggest using GitHub Authorized Keys to provision user accounts and SSH keys. We provide a chart of how we recommend doing it.

Extending

The bastion was written to be easily extensible.

You can extend the enforcement policies by adding shell scripts to etc/enforce.d. Any scripts that are +x (e.g. chmod 755) will be executed at runtime.

Thanks

  • @neochrome, for providing a great basic bastion built on top of Alpine Linux
  • @aws, for providing detailed instructions on how to do SSH session logging.
  • @duo, for providing excellent documentation
  • @google for contributing Google Authenticator to the Open Source community

Quick Start

Here's how you can quickly demo the bastion. We assume you have ~/.ssh/authorized_keys properly configured and your SSH key (e.g. ~/.ssh/id_rsa) added to your SSH agent.

$ docker run -it -p 1234:22 \
     -e MFA_PROVIDER=google-authenticator \
     -v ~/.ssh/authorized_keys:/root/.ssh/authorized_keys \
     cloudposse/bastion

Now, in another terminal you should be able to run:

$ ssh root@localhost -p 1234

The first time you connect, you'll be asked to setup your MFA device. Subsequently, each time you connect, you'll be prompted to enter your MFA token.

Help

Got a question? We got answers.

File a GitHub issue, send us an email or join our Slack Community.

README Commercial Support

DevOps Accelerator for Startups

We are a DevOps Accelerator. We'll help you build your cloud infrastructure from the ground up so you can own it. Then we'll show you how to operate it and stick around for as long as you need us.

Learn More

Work directly with our team of DevOps experts via email, slack, and video conferencing.

We deliver 10x the value for a fraction of the cost of a full-time engineer. Our track record is not even funny. If you want things done right and you need it done FAST, then we're your best bet.

  • Reference Architecture. You'll get everything you need from the ground up built using 100% infrastructure as code.
  • Release Engineering. You'll have end-to-end CI/CD with unlimited staging environments.
  • Site Reliability Engineering. You'll have total visibility into your apps and microservices.
  • Security Baseline. You'll have built-in governance with accountability and audit logs for all changes.
  • GitOps. You'll be able to operate your infrastructure via Pull Requests.
  • Training. You'll receive hands-on training so your team can operate what we build.
  • Questions. You'll have a direct line of communication between our teams via a Shared Slack channel.
  • Troubleshooting. You'll get help to triage when things aren't working.
  • Code Reviews. You'll receive constructive feedback on Pull Requests.
  • Bug Fixes. We'll rapidly work with you to fix any bugs in our projects.

Slack Community

Join our Open Source Community on Slack. It's FREE for everyone! Our "SweetOps" community is where you get to talk with others who share a similar vision for how to rollout and manage infrastructure. This is the best place to talk shop, ask questions, solicit feedback, and work together as a community to build totally sweet infrastructure.

Discourse Forums

Participate in our Discourse Forums. Here you'll find answers to commonly asked questions. Most questions will be related to the enormous number of projects we support on our GitHub. Come here to collaborate on answers, find solutions, and get ideas about the products and services we value. It only takes a minute to get started! Just sign in with SSO using your GitHub account.

Newsletter

Sign up for our newsletter that covers everything on our technology radar. Receive updates on what we're up to on GitHub as well as awesome new projects we discover.

Office Hours

Join us every Wednesday via Zoom for our weekly "Lunch & Learn" sessions. It's FREE for everyone!

zoom

Contributing

Bug Reports & Feature Requests

Please use the issue tracker to report any bugs or file feature requests.

Developing

If you are interested in being a contributor and want to get involved in developing this project or help out with our other projects, we would love to hear from you! Shoot us an email.

In general, PRs are welcome. We follow the typical "fork-and-pull" Git workflow.

  1. Fork the repo on GitHub
  2. Clone the project to your own machine
  3. Commit changes to your own branch
  4. Push your work back up to your fork
  5. Submit a Pull Request so that we can review your changes

NOTE: Be sure to merge the latest changes from "upstream" before making a pull request!

Copyright

Copyright © 2017-2023 Cloud Posse, LLC

License

License

See LICENSE for full details.

Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

  https://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License.

Trademarks

All other trademarks referenced herein are the property of their respective owners.

About

This project is maintained and funded by Cloud Posse, LLC. Like it? Please let us know by leaving a testimonial!

Cloud Posse

We're a DevOps Professional Services company based in Los Angeles, CA. We ❤️ Open Source Software.

We offer paid support on all of our projects.

Check out our other projects, follow us on twitter, apply for a job, or hire us to help with your cloud strategy and implementation.

Contributors

Erik Osterman
Erik Osterman
Marji Cermak
Marji Cermak

README Footer Beacon

bastion's People

Contributors

alebabai avatar dependabot[bot] avatar goruha avatar jawabuu avatar jonmchan avatar marji avatar max-lobur avatar mrwacky42 avatar osterman avatar paulcalabro avatar vadim-hleif avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

bastion's Issues

Jump host not working

Hello,

When I try to use my container as a jump host I get the following error on the container log: refused local port forward: originator 0.0.0.0 port 0, target XXXX port 22.

Do you have an idea?

ARM64 docker image of releases

Describe the Feature

When creating new releases, build an arm64 Docker image for those wanting to deploy to AWS arm64 EC2 instances, ECS or K8s clusters instead of building an image locally and deploying that.

Document openssh patches

There are quite a few patches in the Dockerfile applied to openssh before it is compiled.

Could these patches, their source and purpose be documented, please? As the bastion server security is very important, any changes to the openssh implementation should be documented so it can be audited.

Also, would the current patch set prevent upgrading the Dockerfile to use the current openssh version V_7_6_P1 instead of V_7_4_P1 which is used currently?

Thank you!

Latest Tag Won't Start

Anyone else experiencing the following or is it just me?

Initializing duo
Initializing enforcer
- Enabling Enforcer
Initializing google-authenticator
- Enabling Google Authenticator MFA
Initializing hostname
Initializing rate-limit
- Enabling Rate Limits
- Users will be locked for 300s after 5 failed logins
- Fail delay of 3000000 micro-seconds
Initializing secure-proc
- Locking down /proc
Initializing slack
- Enabling Slack Notifications
Initializing ssh-audit
- Enabling SSH Audit Logs
/etc/init.d/ssh-audit: line 13: chsh: command not found
FATAL: Failed to initialize

chsh is missing?

I'm using the latest image:

cloudposse/bastion                           latest              1b9553c91078        5 days ago          314MB

I reverted to tag 0.2.0 and it starts up for me with no issue.

Duo Does work with latest build

Thanks for doing this! Was able to get Google auth set up fine, but eventually wanted to switch to Duo.

Looks like when the switch to multi-stage build was made, a bug was introduced. The locations of the pamduo libs is not copied correctly from the builder image, so you get an error saying that module cannot be found for user root.

Put a patch together locally but github is flaky tonight. The prefix command to duo pam doesn't do anything. make install still puts the libs in /lib64/security. This is not copied to the main image.

I added:
COPY --from=duo-builder lib64/ /lib/

after line 98. This works.

Example for AWS ECS

This bastion host is bloody useful and will save our team an enormous effort, thanks!

I had a little trouble working out how to run this on ECS so I'm posting my cloudformation template here for anyone that is looking to do the same:

AWSTemplateFormatVersion: 2010-09-09
Description: Bastion

Parameters:

  KeyPairName:
    Description: >-
      Enter a Public/private key pair. If you do not have one in this region,
      please create it before continuing
    Type: 'AWS::EC2::KeyPair::KeyName'
  NumBastionHosts:
    AllowedValues:
      - '1'
      - '2'
      - '3'
      - '4'
    Default: '1'
    Description: Enter the number of bastion hosts to create
    Type: String
  NetworkStackName:
    Description: Name of an active CloudFormation stack of networking resources
    Type: String
    MinLength: 1
    MaxLength: 255
    AllowedPattern: "^[a-zA-Z][-a-zA-Z0-9]*$"

Resources:

  BastionAutoScalingGroup:
    Type: 'AWS::AutoScaling::AutoScalingGroup'
    Properties:
      LaunchConfigurationName: !Ref BastionLaunchConfiguration
      VPCZoneIdentifier:
        - !ImportValue
            Fn::Sub: "${NetworkStackName}-PublicSubnet1ID"
        - !ImportValue
            Fn::Sub: "${NetworkStackName}-PublicSubnet2ID"
        - !ImportValue
            Fn::Sub: "${NetworkStackName}-PublicSubnet3ID"
      MinSize: 0
      MaxSize: 3
      Cooldown: '300'
      DesiredCapacity: !Ref NumBastionHosts
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}
          PropagateAtLaunch: 'true'
    CreationPolicy:
      ResourceSignal:
        Count: !Ref NumBastionHosts
        Timeout: PT30M

  BastionECSCluster:
    Type: AWS::ECS::Cluster
    Properties:
      ClusterName: !Sub ${AWS::StackName}

  BastionEC2Role:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
        - Effect: Allow
          Principal:
            Service: [ec2.amazonaws.com]
          Action: ['sts:AssumeRole']
      Path: /
      Policies:
      - PolicyName: ecs-service
        PolicyDocument:
          Statement:
          - Effect: Allow
            Action: [
              'ecs:CreateCluster',
              'ecs:DeregisterContainerInstance',
              'ecs:DiscoverPollEndpoint',
              'ecs:Poll',
              'ecs:RegisterContainerInstance',
              'ecs:StartTelemetrySession',
              'ecs:Submit*',
              "ecr:GetAuthorizationToken",
              "ecr:BatchCheckLayerAvailability",
              "ecr:GetDownloadUrlForLayer",
              "ecr:BatchGetImage",
              'logs:CreateLogStream',
              'logs:PutLogEvents'
            ]
            Resource: '*'

  BastionEC2InstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Path: /
      Roles: [!Ref 'BastionEC2Role']

  BastionLaunchConfiguration:
    Type: AWS::AutoScaling::LaunchConfiguration
    Metadata:
      AWS::CloudFormation::Init:
        config:
          files:
            /usr/bin/github-authorized-keys:
              content: |
                      #!/bin/sh
                      set -ue
                      API_URL="${API_URL:-http://github-authorized-keys:301/user/%s/authorized_keys}"
                      if [ -n "$1" ]; then
                        exec curl --silent --fail $(printf "$API_URL" "$1")
                      else
                        echo "Usage: $0 [github username]"
                      fi
              mode: '000550'
              owner: root
              group: root
            /etc/ssh/cloudposse_sshd_config:
              content: |
                  Port 22
                  AddressFamily any
                  ListenAddress 0.0.0.0
                  ListenAddress ::

                  Protocol 2
                  HostKey /etc/ssh/ssh_host_rsa_key

                  # Lifetime and size of ephemeral version 1 server key
                  #KeyRegenerationInterval 1h
                  #ServerKeyBits 1024

                  # Ciphers and keying
                  #RekeyLimit default none

                  # Logging
                  # obsoletes QuietMode and FascistLogging
                  #SyslogFacility AUTH
                  #LogLevel INFO

                  # Authentication:

                  LoginGraceTime 2m
                  PermitRootLogin yes
                  PermitUserRC no
                  StrictModes no
                  MaxAuthTries 6
                  MaxSessions 10

                  PubkeyAuthentication yes

                  # The default is to check both .ssh/authorized_keys and .ssh/authorized_keys2
                  # but this is overridden so installations will only check .ssh/authorized_keys
                  AuthorizedKeysFile  .ssh/authorized_keys

                  #AuthorizedPrincipalsFile none

                  # Don't read the user's ~/.rhosts and ~/.shosts files
                  IgnoreRhosts yes

                  # To disable tunneled clear text passwords, change to no here!
                  #PasswordAuthentication yes
                  PermitEmptyPasswords no

                  # Change to no to disable s/key passwords
                  ChallengeResponseAuthentication yes

                  UsePAM yes
                  AuthenticationMethods publickey,keyboard-interactive
                  AllowAgentForwarding yes
                  AllowTcpForwarding no
                  GatewayPorts no
                  X11Forwarding no
                  PermitTTY yes
                  PrintMotd no
                  PrintLastLog yes
                  TCPKeepAlive yes
                  #UseLogin no
                  UsePrivilegeSeparation sandbox
                  PermitUserEnvironment no
                  #Compression delayed
                  ClientAliveInterval 30
                  ClientAliveCountMax 3
                  UseDNS no
                  #PidFile /run/sshd.pid
                  PermitTunnel yes
                  ChrootDirectory none
                  VersionAddendum none

                  # no default banner path
                  Banner none

                  # override default of no subsystems
                  Subsystem  sftp  /usr/lib/ssh/sftp-server -l VERBOSE

                  # the following are HPN related configuration options
                  # tcp receive buffer polling. disable in non autotuning kernels
                  #TcpRcvBufPoll yes

                  # disable hpn performance boosts
                  #HPNDisabled no

                  # buffer size for hpn to non-hpn connections
                  #HPNBufferSize 2048

                  ForceCommand /usr/bin/fc

                  # Example of overriding settings on a per-user basis
                  #Match User anoncvs
                  #  X11Forwarding no
                  #  AllowTcpForwarding no
                  #  PermitTTY no
                  #  ForceCommand cvs server

                  AuthorizedKeysCommand /usr/bin/github-authorized-keys
                  AuthorizedKeysCommandUser root
    Properties:
      ImageId: ami-0092e55c70015d8c3 # ECS AMI
      InstanceType: t2.micro
      IamInstanceProfile:
        Ref: BastionEC2InstanceProfile
      KeyName:
        Ref: KeyPairName
      SecurityGroups:
        - !ImportValue
          Fn::Sub: "${NetworkStackName}-BastionSecurityGroupID"
      AssociatePublicIpAddress: true
      UserData:
        Fn::Base64: !Sub |
          #!/bin/bash -xe

          yum install -y aws-cfn-bootstrap

          echo ECS_CLUSTER=${AWS::StackName} >> /etc/ecs/ecs.config

          # Process the default configset from the CloudFormation::Init metadata
          /opt/aws/bin/cfn-init -v \
              --region ${AWS::Region} \
              --stack ${AWS::StackName} \
              --resource BastionLaunchConfiguration \
              --configsets default

          # Signal BastionAutoScalingGroup with the cfn-init exit status
          /opt/aws/bin/cfn-signal -e $? \
              --region ${AWS::Region} \
              --stack ${AWS::StackName} \
              --resource BastionAutoScalingGroup

  TaskDefinition:
    Type: AWS::ECS::TaskDefinition
    Properties:
      ContainerDefinitions:
        - Name: 'github-authorized-keys'
          MountPoints:
            - SourceVolume: "host"
              ContainerPath: "/host"
          Image: "cloudposse/github-authorized-keys"
          Cpu: "100"
          Memory: "64"
          Essential: "true"
          Environment:
            - Name: GITHUB_API_TOKEN
              Value: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
            - Name: GITHUB_ORGANIZATION
              Value: xxxxxx
            - Name: GITHUB_TEAM
              Value: xxxxx
            - Name: SYNC_USERS_SHELL
              Value: /bin/bash
            - Name: SYNC_USERS_ROOT
              Value: /host
            - Name: SYNC_USERS_INTERVAL
              Value: 300
            - Name: LISTEN
              Value: :301
            - Name: INTEGRATE_SSH
              Value: 'false'
            - Name: LINUX_USER_ADD_TPL
              Value: 'adduser -s {shell} {username}'
            - Name: LINUX_USER_ADD_WITH_GID_TPL
              Value: 'adduser -s {shell} -G {group} {username}'
          PortMappings:
            - ContainerPort: 301
              HostPort: 301
              Protocol: tcp

        - Name: 'bastion'
          MountPoints:
            - SourceVolume: "root"
              ContainerPath: "/root"
            - SourceVolume: "home"
              ContainerPath: "/home"
            - SourceVolume: "etc-shadow"
              ContainerPath: "/etc/shadow"
            - SourceVolume: "etc-passwd"
              ContainerPath: "/etc/passwd"
            - SourceVolume: "etc-group"
              ContainerPath: "/etc/group"
            - SourceVolume: "sshd_config"
              ContainerPath: "/etc/ssh/sshd_config"
            - SourceVolume: "usr-bin-github-authorized-keys"
              ContainerPath: "/usr/bin/github-authorized-keys"
          Image: "cloudposse/bastion"
          Cpu: "100"
          Memory: "128"
          Essential: "true"
          Links: 
            - github-authorized-keys
          Environment:
            - Name: DUO_IKEY
              Value: xxxxxxxxxxxxxxxxxxx
            - Name: DUO_SKEY
              Value: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
            - Name: DUO_HOST
              Value: api-xxxxx.duosecurity.com
            - Name: SSH_AUDIT_ENABLED
              Value: 'false'
          PortMappings:
            - ContainerPort: 22
              HostPort: 1234
              Protocol: tcp
      Volumes:
        - Name: "host"
          Host:
            SourcePath: "/"
        - Name: "root"
          Host:
            SourcePath: "/root"
        - Name: "home"
          Host:
            SourcePath: "/home"
        - Name: "etc-shadow"
          Host:
            SourcePath: "/etc/shadow"
        - Name: "etc-passwd"
          Host:
            SourcePath: "/etc/passwd"
        - Name: "etc-group"
          Host:
            SourcePath: "/etc/group"
        - Name: "sshd_config"
          Host:
            SourcePath: "/etc/ssh/cloudposse_sshd_config"
        - Name: "usr-bin-github-authorized-keys"
          Host:
            SourcePath: "/usr/bin/github-authorized-keys"
           

  ECSService:
    Type: AWS::ECS::Service
    Properties:
      Cluster: !Sub ${AWS::StackName}
      DesiredCount: !Ref NumBastionHosts
      TaskDefinition: !Ref TaskDefinition
      DeploymentConfiguration:
        MinimumHealthyPercent: 0

Duo Tester

I am helping to release new versions of bastion, however I do not use Duo MFA. I'm requesting for anyone in the community that uses Duo to please help test that #70 the latest releases still work with Duo authentication.

Additionally, if anyone can think of a basic functional/integation test for Duo and add it to the project (in the test folder), that would be awesome.

Thanks!

make readme fails

Cannot regenerate the readme currently on my machine.

Ran:

make init
make readme/deps
make readme

This errors out with:

$ make readme
* Package gomplate already installed
make: gomplate: No such file or directory
make: *** [readme/build] Error 1

ansible fails on bastion

ansible executes below command and it fails at 9.shell exec command

ssh 172.21.2.54 '/bin/sh -c '"'"'echo "pwd" && sleep 0'"'"''

ssh config help

Is it possible to use this bastion as a forwarding agent when supplying a private key to the destination host? I can't seem to get the following to work?

Host bastion
  HostName <bastion-ip>
  Port 1234
  ForwardAgent   yes

Host 10.0.1.23
  IdentityFile ~/.ssh/key.pem
  ProxyCommand ssh dmcd@bastion -W %h:%p

chsh: PAM: Authentication failure

Hi,

I can't get the latest version to run. 0.4.4 works fine.

docker run -it -p 1234:22 \
     -e MFA_PROVIDER=google-authenticator \
     -v ~/.ssh/authorized_keys:/root/.ssh/authorized_keys \
     cloudposse/bastion:latest
Initializing duo
Initializing enforcer
- Enabling Enforcer
- Enabling Clean Home
Initializing google-authenticator
- Enabling Google Authenticator MFA
Initializing hostname
Initializing rate-limit
- Enabling Rate Limits
- Users will be locked for 300s after 5 failed logins
- Fail delay of 3000000 micro-seconds
Initializing secure-proc
- Locking down /proc
Initializing slack
Initializing ssh-audit
- Enabling SSH Audit Logs
Password:

It ask for an password and then outputs:

chsh: PAM: Authentication failure
FATAL: Failed to initialize

System: macOS 10.14.5 with Docker version 18.09.2, build 6247962

Is there a way to enable transparent ssh tunneling?

Hi, I'm relatively new to bastion servers so I'm not sure whether ssh tunneling is a standard feature or if it is just a common use-case, but I would like to spin up this bastion on ECS in a public subnet and simple forward some database traffic to the private subnet that the database lives in -- rather than executing the database client on the bastion host itself.

So the end system is: postgresql client on a laptop -> bastion host forwards port 1234 to private subnet port 5432 if MFA is satisfied -> postgresql database accepts connections on 5432.

Curious if this is possible as is or needs another container, thanks!

Bind-Mount Recommendations Result In Error

Bind-mount /etc/passwd, /etc/shadow and /etc/group into the container as read-only

When attempting to do this, the docker container fails to startup. The error in the logs show as:

- Enabling SSH Audit Logs
chsh: failure while writing changes to /etc/passwd

This is because chsh is run on startup -

chsh -s /usr/bin/sudosh root
.

The code should be updated to allow passwd, shadow, and group to not be modified during normal usage or the recommendation to keep those files mounted as read-only should be removed.

Weird issue re: failed logins

I've seen this error occur a few times so I think it might be a bug:

$ ssh -i id_rsa <some_host> -l <some_user>

Account locked due to 9 failed logins

Account locked due to 10 failed logins

Account locked due to 11 failed logins

It's odd b/c the user is logging in with a key. I think it should either work or not. And for the most part it works, however, this happens on occasion. Any idea what's causing this?

PAM: Error in service module for <username> from <ip>

Getting the error in title when I try to authenticate, any ideas as to why?

Docker-compose

bastion:
  image: cloudposse/bastion
  restart: unless-stopped
  hostname: <redacted>
  volumes:
    - /home:/home
    - /etc/passwd:/etc/passwd:ro
    - /etc/shadow:/etc/shadow:ro
    - /etc/group:/etc/group:ro
    - ${STORAGE_DIR}/bastion/ssh:/etc/ssh
  environment:
    - DUO_IKEY=<redacted>
    - DUO_SKEY=<redacted>
    - DUO_HOST=<redacted>
  networks:
    - dmz

Logs

bastion_1          | Initializing duo
bastion_1          | - Enabling DUO MFA
bastion_1          | Initializing enforcer
bastion_1          | - Enabling Enforcer
bastion_1          | - Enabling Clean Home
bastion_1          | Initializing google-authenticator
bastion_1          | Initializing hostname
bastion_1          | Initializing rate-limit
bastion_1          | - Enabling Rate Limits
bastion_1          | - Users will be locked for 300s after 5 failed logins
bastion_1          | - Fail delay of 3000000 micro-seconds
bastion_1          | Initializing secure-proc
bastion_1          | - Locking down /proc
bastion_1          | Initializing slack
bastion_1          | Initializing ssh-audit
bastion_1          | - Disabling SSH Audit Logs
bastion_1          | Initializing ssh-authorized-keys-command
bastion_1          | Initializing ssh-host-key
bastion_1          | Server listening on :: port 22.
bastion_1          | Server listening on 0.0.0.0 port 22.
bastion_1          | PAM: Error in service module for <username> from <ip>
bastion_1          | Connection closed by authenticating user <username> <ip> port 37642 [preauth]

The test user exists within Duo with corresponding username

User Accounts & SSH Keys Chart is missing

In the documentation on this part:

User Accounts & SSH Keys
The bastion does not attempt to manage user accounts. We suggest using GitHub Authorized Keys to provision user accounts and SSH keys. We provide a chart of how we recommend doing it.

Is missing the chart.

Project abandoned?

Hi!

What is the status of this project? I was looking around for an ssh jump host with 2FA support, and found this, which seemed perfect. However, the project seems to have stalled in the last few years, and hasn't been kept up to date with Alpine, etc., even though there are pending pull requests in that direction. It would make me uneasy to rely on old versions of sshd etc.

So, is this project no longer maintained? Is there some alternative fork people are working on instead?

Slack Notification Fails because Root CA Certs Out of Date

Getting a curl: (60) SSL certificate problem: certificate has expired when trying to send the slack notification.

The Root CA Certs have expired and need to be updated.

The following commands work to fix the issue:

sed -i 's|^mozilla\/DST_Root_CA_X3\.crt|!mozilla/DST_Root_CA_X3.crt|' /etc/ca-certificates.conf
curl -sk https://letsencrypt.org/certs/isrgrootx1.pem -o /usr/local/share/ca-certificates/ISRG_Root_X1.crt
update-ca-certificates --fresh

The following errors/warnings may be produced, but they do not keep the issue from being resolved.

Warning! Cannot copy to bundle: /usr/share/ca-certificates/mozilla/AddTrust_External_Root.crt
Warning! Cannot copy to bundle: /usr/share/ca-certificates/mozilla/Certinomis_-_Root_CA.crt
Warning! Cannot copy to bundle: /usr/share/ca-certificates/mozilla/Certplus_Class_2_Primary_CA.crt
Warning! Cannot copy to bundle: /usr/share/ca-certificates/mozilla/Deutsche_Telekom_Root_CA_2.crt
Warning! Cannot copy to bundle: /usr/share/ca-certificates/mozilla/Swisscom_Root_CA_2.crt
Warning! Cannot copy to bundle: /usr/share/ca-certificates/mozilla/UTN_USERFirst_Email_Root_CA.crt
Warning! Cannot symlink /usr/share/ca-certificates/mozilla/ISRG_Root_X1.crt -> /etc/ssl/certs/ca-cert-ISRG_Root_X1.pem
WARNING: ca-certificates.crt does not contain exactly one certificate or CRL: skipping

Documentation outdated.

The bastion does not attempt to manage user accounts. We suggest using GitHub Authorized Keys to provision user accounts and SSH keys. We provide a chart of how we recommend doing it.

The chart is offline, could anyone provide it?

Convert to Multi-Stage Docker Build

what

  • Use multi-stage build process
  • Decompose && build pipeline into separate RUN commands

why

  • While virtual packages address this, delineating between the build stage and the runtime stage makes it easier to understand what's going on

related

Google Authenticator only works with emergency codes

Hi,

First off all: thanks for the great image!
I use Google Authenticator (on Android) successfully on other accounts, but I cannot use it with your image. Docker logs just say:

PAM: Authentication failure for root from 172.17.0.1
Connection closed by 172.17.0.1 port 54450 [preauth]

I can use the emergency codes that are generated.

Any suggestions? Thanks.

sftp - Received message too long

I noticed sftp to the bastion container (with google authenticator selected as the MFA) does not work:

Provision a fresh bastion instance:

$ docker run -it -p 1234:22 \
     -e MFA_PROVIDER=google-authenticator \
     -v ~/.ssh/authorized_keys:/root/.ssh/authorized_keys
     cloudposse/bastion:latest

Initialise with the first login.
Then ssh into the container again, works fine:

$ ssh root@localhost -p 1234
Verification code: 

WARNING: Unauthorized access to this system is forbidden and will be
prosecuted by law. By accessing this system, you agree that your actions
may be monitored for any reason.

3ee8753d97ea [~]#

But SFTP stops with an error:

$ sftp -P 1234 root@localhost
Verification code: 
Received message too long 1296449824

I'm not sure where to look. Perhaps the sshd config? If you give me a little hint, I'm happy to debug more.

SLACK_FATAL_ERRORS does not actually do anything in sshrc

Found a bug? Maybe our Slack Community can help.

Slack Community

Describe the Bug

when enabling SLACK_FATAL_ERRORS, the user should be logged out when the slack notification fails. However, this does not happen when using sshrc SLACK_HOOK method.

The reason is that exit 1 in https://github.com/cloudposse/bastion/blob/master/rootfs/etc/ssh/sshrc does not do anything. The ssh command runs that and happily goes into the shell after the error exit code.

For this to be effective, replacing exit 1 with kill -TERM $PPID makes this actually die and the ssh connection to close when the SLACK_FATAL_ERRORS occur.

Possibly consider disabling this line by default

It might be good to disable this line by default:

MaxSessions 10

By using this default value, a user can use SSH multiplexing on their side:

Host *
  ControlMaster auto
  ControlPath ~/.ssh/control-sockets/%C
  ControlPersist yes
  LogLevel QUIET
  ServerAliveCountMax 5
  ServerAliveInterval 60

While this speeds things up, it has the side effect of using 2FA the first connection attempt and reusing that existing authenticated connection for all future connections. The keep-alive keeps the connection from getting severed.

If that machine on the untrusted network gets popped and the bad actor enumerates the control sockets or forces these settings upon the user, they could potentially bypass 2FA altogether.

Limiting MaxSessions would administratively make that not possible.

Thoughts?

PAM: Module is unknown for root from <IP>

So I was testing the project on AWS EC2 instance in docker container. After a fairly quick setup I received the following error when trying to login (server logs);

PAM: Module is unknown for root from <IP>
Connection closed by authenticating user root <IP> port 3445 [preauth]

The following is an original SSH command executed from my local host;

ssh -p 1234 root@<ip>

Key authentication passed successfully and I was prompted for SSH key password.

This is a Makefile I've used to setup the whole thing on EC2 instance;

SHELL := bash
MAKEFLAGS += --warn-undefined-variables
.SHELLFLAGS := -euo pipefail -c


DOCKER_OPTS := \
        -it \
        -e MFA_PROVIDER=duo \
        -e DUO_IKEY=<redacted> \
        -e DUO_SKEY=<redacted> \
        -e DUO_HOST=<redacted> \
        -e SLACK_ENABLED=true \
        -e SLACK_WEBHOOK_URL=<redacted> \
        -v `pwd`/authorized_keys:/root/.ssh/authorized_keys \
        -p 1234:22

.PHONY: all
all:

.PHONY: dbuild
dbuild:
        docker build . -t cloudposse/bastion:latest

.PHONY: drun
drun: dbuild
        docker run $(DOCKER_OPTS) \
                cloudposse/bastion:latest

I think the root cause is some DUO-related issues, probably related to #34.

Any clue where I went wrong with the setup?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.