# Bastion in kOps

Bastion provide an external facing point of entry into a network containing private network instances. This host can provide a single point of fortification or audit and can be started and stopped to enable or disable inbound SSH communication from the Internet, some call bastion as the "jump server".

* [More information on bastion from aws](http://docs.aws.amazon.com/quickstart/latest/linux-bastion/architecture.html)
* [More information on bastion from gce](https://cloud.google.com/solutions/connecting-securely#bastion)

## AWS

### Enable/Disable bastion

To enable a bastion instance group, a user will need to set the `--bastion` flag on cluster create

```yaml
kops create cluster --topology private --networking $provider --bastion $NAME
```

To add a bastion instance group to a pre-existing cluster, create a new instance group with the `--role Bastion` flag and one or more subnets (e.g. `utility-us-east-2a,utility-us-east-2b`). 
```yaml
kops create instancegroup bastions --role Bastion --subnet $SUBNET
```

### Configure the bastion instance group

You can edit the bastion instance group to make changes. By default the name of the bastion instance group will be `bastions` and you can specify the name of the cluster with `--name` as in:

```yaml
kops edit ig bastions --name $KOPS_NAME
```

You should now be able to edit and configure your bastion instance group.

```yaml
apiVersion: kops.k8s.io/v1alpha2
kind: InstanceGroup
metadata:
  name: bastions
spec:
  associatePublicIp: true
  image: ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-20220404
  machineType: t2.micro
  maxSize: 1
  minSize: 1
  role: Bastion
  subnets:
  - utility-us-east-2a
```

**Note**: If you want to turn off the bastion server, you must set the instance group `maxSize` and `minSize` fields to `0`.

If you do not want the bastion instance group created at all, simply drop the `--bastion` flag off of your create command. The instance group will never be created.


### Using a public CNAME to access your bastion

By default the bastion instance group will create a public CNAME alias that will point to the bastion ELB.

The default bastion name is `bastion.$NAME` as in

```yaml
bastion.mycluster.example.com
```

Unless a user is using `--dns-zone` which will inherently use the `bastion-$ZONE` syntax.

You can define a custom bastion CNAME by editing the main cluster config `kops edit cluster $NAME` and modifying the following block

```yaml
spec:
  topology:
    bastion:
      bastionPublicName: bastion.mycluster.example.com
```

### Using an internal (VPC only) load balancer 
{{ kops_feature_table(kops_added_default='1.23') }}

When configuring a LoadBalancer, you can also choose to have a public load balancer or an internal (VPC only) load balancer. The `type` field should be `Public` or `Internal` (defaults to `Public` if omitted).

```yaml
spec:
  topology:
    bastion:
      loadBalancer:
        type: "Internal"
```

### Additional security groups to ELB
{{ kops_feature_table(kops_added_default='1.18') }}

If you want to add security groups to the bastion ELB

```yaml
spec:
  topology:
    bastion:
      bastionPublicName: bastion.mycluster.example.com
      loadBalancer:
        additionalSecurityGroups:
        - "sg-***"
```

### Access when using None-DNS

When using a None-DNS cluster (`--dns=none`), there is no DNS zone where we can configure a
CNAME for the bastion. Because bastions are fronted with a load
balancer, you can instead use the endpoint of the load balancer to
reach your bastion.

On AWS, an easy way to find this DNS name is with kops toolbox:

```
kops toolbox dump -ojson | grep 'bastion.*elb.amazonaws.com'
```

### Changing your ELB idle timeout

The bastion is accessed via an AWS ELB. The ELB is required to gain secure access into the private network and connect the user to the ASG that the bastion lives in. kOps will by default set the bastion ELB idle timeout to 5 minutes. This is important for SSH connections to the bastion that you plan to keep open.

You can increase the ELB idle timeout by editing the main cluster config `kops edit cluster $NAME` and modifying the following block

```yaml
spec:
  topology:
    bastion:
      idleTimeoutSeconds: 1200
```

Where the maximum value is 3600 seconds (60 minutes) allowed by AWS. For more information see [configuring idle timeouts](http://docs.aws.amazon.com/elasticloadbalancing/latest/classic/config-idle-timeout.html).

### Using the bastion

Once your cluster is setup and you need to SSH into the bastion you can access a cluster resource using the following steps

```bash
# Verify you have an SSH agent running. This should match whatever you built your cluster with.
ssh-add -l
# If you need to add the key to your agent:
ssh-add path/to/private/key

# Now you can SSH into the bastion. Substitute the administrative username of the instance's OS for <username> (`ubuntu` for  Ubuntu,  `admin` for Debian, etc.) and the bastion domain for <bastion-domain>. If the bastion doesn't have a public CNAME alias, use the domain of the assigned load balancer as the bastion domain.
ssh -A <username>@<bastion-domain>

# then you can use the fowarded authentication to SSH into control-plane or worker nodes in the cluster.
ssh <username>@<node-address>

```

Now that you can successfully SSH into the bastion with a forwarded SSH agent. You can SSH into any of your cluster resources using their local IP address. You can get their local IP address from the cloud console.
