Is there a way to reach a SFTP server from a serverless service (or local) with a tunnel machine in between? - amazon-web-services

I'm building a serverless service (AWS lambda) to get/put files in SFTP server on a daily basis.
The only way to access the SFTP server is from another machine (an AWS EC2 instance) which has it's IP whitelisted at the SFTP server.
I did try to use Python SSHTunnelForwarder and paramiko libraries, but I'm not sure if it's possible bind SSH (tunnel forwarding) and SFTP in a single solution.
Script
with SSHTunnelForwarder(
(ssh_instance_ip, 22),
ssh_username=ssh_user,
ssh_private_key='<key_path>',
remote_bind_address=('0.0.0.0', 22),
local_bind_address=('127.0.0.1', 10022),
) as tunnel:
tunnel.start()
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(password=sftp_pwd, username=sftp_user, hostname=sftp_host, port='<port_value>', allow_agent=True, disabled_algorithms=dict(pubkeys=["rsa-sha2-512", "rsa-sha2-256"]))
tr = client.get_transport()
tr.default_max_packet_size = 100000000
tr.default_window_size = 100000000
sftp = client.open_sftp()
sftp.listdir('/')
sftp.close
client.close()
Error:
...
DEBUG:paramiko.transport:Sending global request "keepalive#lag.net"
DEBUG:paramiko.transport:[chan 0] EOF sent (0)
DEBUG:paramiko.transport:EOF in transport thread
Traceback (most recent call last):
File "/home/linuxbrew/.linuxbrew/Cellar/python#3.10/3.10.9/lib/python3.10/site-packages/paramiko/sftp_client.py", line 852, in _read_response
t, data = self._read_packet()
File "/home/linuxbrew/.linuxbrew/Cellar/python#3.10/3.10.9/lib/python3.10/site-packages/paramiko/sftp.py", line 201, in _read_packet
x = self._read_all(4)
File "/home/linuxbrew/.linuxbrew/Cellar/python#3.10/3.10.9/lib/python3.10/site-packages/paramiko/sftp.py", line 188, in _read_all
raise EOFError()
EOFError
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/work/scratch/tunnel_test/em_tunnel/app/tunnel_test.py", line 71, in <module>
sftp.listdir('/')
File "/home/linuxbrew/.linuxbrew/Cellar/python#3.10/3.10.9/lib/python3.10/site-packages/paramiko/sftp_client.py", line 218, in listdir
return [f.filename for f in self.listdir_attr(path)]
File "/home/linuxbrew/.linuxbrew/Cellar/python#3.10/3.10.9/lib/python3.10/site-packages/paramiko/sftp_client.py", line 239, in listdir_attr
t, msg = self._request(CMD_OPENDIR, path)
File "/home/linuxbrew/.linuxbrew/Cellar/python#3.10/3.10.9/lib/python3.10/site-packages/paramiko/sftp_client.py", line 822, in _request
return self._read_response(num)
File "/home/linuxbrew/.linuxbrew/Cellar/python#3.10/3.10.9/lib/python3.10/site-packages/paramiko/sftp_client.py", line 854, in _read_response
raise SSHException("Server connection dropped: {}".format(e))
paramiko.ssh_exception.SSHException: Server connection dropped:
I did look for several similar topics and could not find a way to bind SSH and SFTP in a single solution to use in serverless service as AWS Lambda.
Could you help me trying either debugging or suggesting ways (maybe a bash or JavaScript) to bind SSH and SFTP, please?
additional information:
EC2 access is done via user#host and a RSA PRIVATE KEY
SFTP access is done via user#host and a password

I've found a solution using ssh2 lib from JavaScript.
The following script access the SFTP server with a user and password jumping over another machine (an ec2 instance in my case) accessible using an user and a RSA KEY.
The script will list the content of the requested path from the SFTP server and write it's result into my.json file.
Script adapted from those examples ssh2 - npm.
const fs = require('fs');
const path = require('path');
const Client = require('ssh2').Client;
// SSH tunnel details
const sshTunnelIp = "ssh_host";
const sshUser = "ssh_user";
const sshKeyPath = path.resolve(__dirname, "path_to_your_key");
const sshKey = fs.readFileSync(sshKeyPath);
// SFTP server details
const sftpServerIp = "sftp_host";
const sftpUser = "sftp_user";
const sftpPass = "sftp_password";
// Create an SSH client
const sshClient = new Client();
// Connect to the SSH tunnel (EC2 instance)
sshClient.connect({
host: sshTunnelIp,
username: sshUser,
privateKey: sshKey
});
sshClient.on('ready', function() {
// Create an SFTP client and connect to the SFTP server
sshClient.sftp(function(err, sftp) {
if (err) throw err;
// List the content of a given path from the SFTP server
sftp.readdir('path_to_sftp_dir', function(err, list) {
if (err) throw err;
// Write the result to a json file
fs.writeFile(
'./my.json',
JSON.stringify(list),
function (err) {
if (err){
console.error('Something went wrong');
}
}
)
console.log("listing directory", list);
sftp.end();
sshClient.end();
});
});
});

Related

Creating Connection for RedshiftDataOperator

So i when to the airflow documentation for aws redshift there is 2 operator that can execute the sql query they are RedshiftSQLOperator and RedshiftDataOperator. I already implemented my job using RedshiftSQLOperator but i want to do it using RedshiftDataOperator instead, because i dont want to using postgres connection in RedshiftSQLOperator but AWS API.
RedshiftDataOperator Documentation
I had read this documentation there is aws_conn_id in the parameter. But when im trying to use the same connection id there is error.
[2023-01-11, 04:55:56 UTC] {base.py:68} INFO - Using connection ID 'redshift_default' for task execution.
[2023-01-11, 04:55:56 UTC] {base_aws.py:206} INFO - Credentials retrieved from login
[2023-01-11, 04:55:56 UTC] {taskinstance.py:1889} ERROR - Task failed with exception
Traceback (most recent call last):
File "/home/airflow/.local/lib/python3.7/site-packages/airflow/providers/amazon/aws/operators/redshift_data.py", line 146, in execute
self.statement_id = self.execute_query()
File "/home/airflow/.local/lib/python3.7/site-packages/airflow/providers/amazon/aws/operators/redshift_data.py", line 124, in execute_query
resp = self.hook.conn.execute_statement(**filter_values)
File "/home/airflow/.local/lib/python3.7/site-packages/botocore/client.py", line 415, in _api_call
return self._make_api_call(operation_name, kwargs)
File "/home/airflow/.local/lib/python3.7/site-packages/botocore/client.py", line 745, in _make_api_call
raise error_class(parsed_response, operation_name)
botocore.exceptions.ClientError: An error occurred (UnrecognizedClientException) when calling the ExecuteStatement operation: The security token included in the request is invalid.
From task id
redshift_data_task = RedshiftDataOperator(
task_id='redshift_data_task',
database='rds',
region='ap-southeast-1',
aws_conn_id='redshift_default',
sql="""
call some_procedure();
"""
)
What should i fill in the airflow connection ? Because in the documentation there is no example of value that i should fill to airflow. Thanks
Airflow RedshiftDataOperator Connection Required Value
Have you tried using the Amazon Redshift connection? There is both an option for authenticating using your Redshift credentials:
Connection ID: redshift_default
Connection Type: Amazon Redshift
Host: <your-redshift-endpoint> (for example, redshift-cluster-1.123456789.us-west-1.redshift.amazonaws.com)
Schema: <your-redshift-database> (for example, dev, test, prod, etc.)
Login: <your-redshift-username> (for example, awsuser)
Password: <your-redshift-password>
Port: <your-redshift-port> (for example, 5439)
(source)
and an option for using an IAM role (there is an example in the first link).
Disclaimer: I work at Astronomer :)
EDIT: Tested the following with Airflow 2.5.0 and Amazon provider 6.2.0:
Added the IP of my Airflow instance to the VPC security group with "All traffic" access.
Airflow Connection with the connection id aws_default, Connection type "Amazon Web Services", extra: { "aws_access_key_id": "<your-access-key-id>", "aws_secret_access_key": "<your-secret-access-key>", "region_name": "<your-region-name>" }. All other fields blank. I used a root key for my toy-aws. If you use other credentials you need to make sure that IAM role has access and the right permissions to the Redshift cluster (there is a list in the link above).
Operator code:
red = RedshiftDataOperator(
task_id="red",
database="dev",
sql="SELECT * FROM dev.public.users LIMIT 5;",
cluster_identifier="redshift-cluster-1",
db_user="awsuser",
aws_conn_id="aws_default"
)

#google-cloud/storage: A server with the specified hostname could not be found

I'm unable to connect even after providing my service account key file (xxx.json) in my path.
const {Storage} = require('#google-cloud/storage');
const storage = new Storage();
const getTheStuff = async () => {
try {
const results = await storage.getBuckets();
const [buckets] = results;
console.log('Buckets:');
buckets.forEach(bucket => {
console.log(bucket.name);
});
} catch (err) {
console.error('ERROR:', err);
}
}
I try to run this but I get the following in my console. I'm not sure if the authentication has happened and something is wrong with my config, or something else entirely. Looks like the API is being treated like it's running from the google cloud env, hence the connection to an internal hostname is not possible, but this library can be used externally to, so I'm confused.
[Error] A server with the specified hostname could not be found.
[Error] Fetch API cannot load http://metadata.google.internal./computeMetadata/v1/instance due to access control checks.
[Error] Failed to load resource: A server with the specified hostname could not be found. (instance, line 0)
[Log] Buckets: (main.chunk.js, line 83)
[Error] Failed to load resource: The request timed out. (instance, line 0)

EndpointConnectionError: Could not connect to the endpoint URL: "http://169.254.169.254/....."

I am trying to create AWS RDS and deploy lambda function using a python script. However, I am getting below error, looks like it is unable to communicate with the aws commands to create rds.
DEBUG: Caught retryable HTTP exception while making metadata service request to http://169.254.169.254/latest/meta-data/iam/security-credentials/: Could not connect to the endpoint URL: "http://169.254.169.254/latest/meta-data/iam/security-credentials/"
Traceback (most recent call last):
File "/usr/lib/python2.7/site-packages/botocore/utils.py", line 303, in _get_request
response = self._session.send(request.prepare())
File "/usr/lib/python2.7/site-packages/botocore/httpsession.py", line 282, in send raise EndpointConnectionError(endpoint_url=request.url, error=e)
EndpointConnectionError: Could not connect to the endpoint URL: "http://169.254.169.254/latest/meta-data/iam/security-credentials/"
I am getting the aws credentials through SSO okta. In the ~/.aws directory,below are the contents of 'credentials' and 'config' file respectively.
[default]
aws_access_key_id = <Key Id>
aws_secret_access_key = <Secret Key>
aws_session_token = <Token>
[default]
region = us-west-2
```python
```
for az in availability_zones:
if aurora.get_db_instance(db_instance_identifier + "-" + az)[0] != 0:
aurora.create_db_instance(db_cluster_identifier, db_instance_identifier + "-" + az, az, subnet_group_identifier, db_instance_type)
else:
aurora.modify_db_instance(db_cluster_identifier, db_instance_identifier + "-" + az, az, db_instance_type)
# Wait for DB to become available for connection
iter_max = 15
iteration = 0
for az in availability_zones:
while aurora.get_db_instance(db_instance_identifier + "-" + az)[1]["DBInstances"][0]["DBInstanceStatus"] != "available":
iteration += 1
if iteration < iter_max:
logging.info("Waiting for DB instances to become available - iteration " + str(iteration) + " of " + str(iter_max))
time.sleep(10*iteration)
else:
raise Exception("Waiting for DB Instance to become available timed out!")
cluster_endpoint = aurora.get_db_cluster(db_cluster_identifier)[1]["DBClusters"][0]["Endpoint"]
The actual error below, coming from the while loop, DEBUG shows unable to locate credential, but the credential is there. I can deploy an Elastic Beanstalk environment from cli using the same aws credential, but not this. Looks like the above aurora.create_db_instance command failed.
DEBUG: Unable to locate credentials
Traceback (most recent call last):
File "./deploy_api.py", line 753, in <module> sync_rds()
File "./deploy_api.py", line 57, in sync_rds
while aurora.get_db_instance(db_instance_identifier + "-" + az)[1]["DBInstances"][0]["DBInstanceStatus"] != "available":
TypeError: 'NoneType' object has no attribute '__getitem__'
I had this error because an ECS task didn't have permissions to write to DynamoDB. The code causing the problem was:
from boto3 import resource
dynamodb_resource = resource("dynamodb")
The problem was resolved when I filled in the region_name, aws_access_key_id and aws_secret_access_key parameters for the resource() function call.
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/core/session.html#boto3.session.Session.resource
If this doesn't solve your problem then check your code that connects to AWS services and make sure that you are filling in all of the proper function parameters.

How do I connect to host MySQL from AWS SAM local docker instance?

I am trying to invoke my Lambda function using sam local invoke but find that it cannot connect to my host MySQL. I tried adding --docker-network host but it also cannot connect
Traceback (most recent call last):
File "/usr/lib/python3.6/site-packages/docker/api/client.py", line 229, in _raise_for_status
response.raise_for_status()
File "/usr/lib/python3.6/site-packages/requests/models.py", line 935, in raise_for_status
raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 400 Client Error: Bad Request for url: http+docker://localhost/v1.35/networks/6ad3bd87e8437e8410145d169a4edf68d1b0247a67257ce7dd1208dac3664c82/connect
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/usr/bin/sam", line 11, in <module>
load_entry_point('aws-sam-cli==0.5.0', 'console_scripts', 'sam')()
File "/usr/lib/python3.6/site-packages/click/core.py", line 722, in __call__
return self.main(*args, **kwargs)
File "/usr/lib/python3.6/site-packages/click/core.py", line 697, in main
rv = self.invoke(ctx)
File "/usr/lib/python3.6/site-packages/click/core.py", line 1066, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "/usr/lib/python3.6/site-packages/click/core.py", line 1066, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "/usr/lib/python3.6/site-packages/click/core.py", line 895, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "/usr/lib/python3.6/site-packages/click/core.py", line 535, in invoke
return callback(*args, **kwargs)
File "/usr/lib/python3.6/site-packages/click/decorators.py", line 64, in new_func
return ctx.invoke(f, obj, *args[1:], **kwargs)
File "/usr/lib/python3.6/site-packages/click/core.py", line 535, in invoke
return callback(*args, **kwargs)
File "/usr/lib/python3.6/site-packages/samcli/commands/local/invoke/cli.py", line 47, in cli
docker_network, log_file, skip_pull_image, profile) # pragma: no cover
File "/usr/lib/python3.6/site-packages/samcli/commands/local/invoke/cli.py", line 79, in do_cli
stderr=context.stderr)
File "/usr/lib/python3.6/site-packages/samcli/commands/local/lib/local_lambda.py", line 80, in invoke
stdout=stdout, stderr=stderr)
File "/usr/lib/python3.6/site-packages/samcli/local/lambdafn/runtime.py", line 83, in invoke
self._container_manager.run(container)
File "/usr/lib/python3.6/site-packages/samcli/local/docker/manager.py", line 61, in run
container.create()
File "/usr/lib/python3.6/site-packages/samcli/local/docker/container.py", line 115, in create
network.connect(self.id)
File "/usr/lib/python3.6/site-packages/docker/models/networks.py", line 57, in connect
container, self.id, *args, **kwargs
File "/usr/lib/python3.6/site-packages/docker/utils/decorators.py", line 19, in wrapped
return f(self, resource_id, *args, **kwargs)
File "/usr/lib/python3.6/site-packages/docker/api/network.py", line 248, in connect_container_to_network
self._raise_for_status(res)
File "/usr/lib/python3.6/site-packages/docker/api/client.py", line 231, in _raise_for_status
raise create_api_error_from_http_exception(e)
File "/usr/lib/python3.6/site-packages/docker/errors.py", line 31, in create_api_error_from_http_exception
raise cls(e, response=response, explanation=explanation)
docker.errors.APIError: 400 Client Error: Bad Request ("container cannot be disconnected from host network or connected to host network")
I noticed the last line:
docker.errors.APIError: 400 Client Error: Bad Request ("container cannot be disconnected from host network or connected to host network")
How do I fix this?
I can't say why --docker-network host produces this error, but I don't think you need it. I can connect to MySQL running on my local machine from within SAM local, without any network overrides.
I do this by simply using my local IP (as opposed to localhost or 127.0.0.1) to connect to the database.
The following lambda function connects to my local MySQL just fine, provided I use my local IP, as revealed a tool like ipconfig.
'use strict';
var mysql = require('mysql');
var connection = mysql.createConnection({
host : '192.168.1.6',
user : 'mike',
password : 'password',
database : 'logtest'
});
module.exports.hello = (event, context, callback) => {
connection.connect();
connection.query('SELECT 1 + 1 AS solution', function (error, results, fields) {
if (error) throw error;
console.log('The solution is: ', results[0].solution);
const response = {
statusCode: 200,
body: JSON.stringify({solution: results[0].solution})
};
connection.end();
callback(null, response);
});
};
Partial ipconfig output:
Ethernet adapter Local Area Connection 6:
Connection-specific DNS Suffix . :
Link-local IPv6 Address . . . . . : fe80::95c2:495c:7226:8ac2%39
IPv4 Address. . . . . . . . . . . : 10.251.19.6
Subnet Mask . . . . . . . . . . . : 255.255.255.0
Default Gateway . . . . . . . . . :
Wireless LAN adapter Wireless Network Connection:
Connection-specific DNS Suffix . :
Link-local IPv6 Address . . . . . : fe80::496a:d34d:8380:3b1c%15
IPv4 Address. . . . . . . . . . . : 192.168.1.6
Subnet Mask . . . . . . . . . . . : 255.255.255.0
Default Gateway . . . . . . . . . : 192.168.1.1
In this case, my lambda function can connect to local MySQL using 10.251.19.6 or 192.168.1.6.
Minimal example here.
Could you post how you are starting mysql container locally? Hard to say whats going wrong with out more info.
Here is some general advice though.
If your running on a mac
You can just use special host name locally when configuring mysql client in container making the call. It will resolve locally with no --docker-network flag needed.
Ex:
host = 'docker.for.mac.localhost'
Or on newer installs of docker https://docs.docker.com/docker-for-mac/release-notes/#docker-community-edition-17120-ce-mac49-2018-01-19
host = 'docker.for.mac.host.internal'
Ex python code.
import mysql.connector
host = 'docker.for.mac.host.internal'
cnx = mysql.connector.connect(user='scott', password='password',
host=host,
database='employees')
cnx.close()
If you are not on mac
Then make sure you are passing --docker-network when you start your mysql container it should look something like this.
docker run -d -v "$PWD":/var/lib/mysql -p 3306:3306 \
--network lambda-local \
--name mysql \
mysql
Then when invoking locally
sam local invoke --docker-network lambda-local
Then in your lambda code you just use network --name you passed mysql container as hostname.
Ex:
import mysql.connector
host = 'mysql'
cnx = mysql.connector.connect(user='scott', password='password',
host=host,
database='employees')
cnx.close()
No configuration need just add below host while connection to your mysql
for windows : docker.for.win.localhost
for mac : docker.for.mac.localhost
const con = require('serverless-mysql')({
config: {
host : 'docker.for.win.localhost',
database : 'db-name',
user : 'root',
connectTimeout : 5000,
password : ''
}
});
You can check cases as follows:
Whether the docker port has a mapping.
Check the port of AWS's security group.

Salt masters behind ELB have flaky connection to minions

I am running the following setup at AWS:
Elastic Loadbalancer in front of two EC2 machines (Amazon Linux) with a docker container that the salt-master runs in
Two EC2 instances with salt-minions installed
The 'master' value in the minion config is set to the dns of the loadbalancer (SaltMaster-env-vpc-test.szfegmankg.us-east-1.elasticbeanstalk.com)
The ELB accepts all traffic from the minions
The Salt-masters accept all traffic from the ELB as well as from the minions
The Salt-masters PKI Folder is shared between the two masters
The Salt-masters have the same private+public keys
The Salt-masters run on 2017.7.1
The Salt-minions run on 2016.11.5 (I tried it with 2017.7.1, but got the same results)
The Salt-minions accept all traffic from the ELB as well as from the masters
The master config looks as follows:
open_mode: True
worker_threads: 20
auto_accept: True
log_level: error
log_level_logfile: debug
extension_modules: srv/salt/ext
rest_cherrypy:
port: 8000
disable_ssl: True
debug: True
external_auth:
pam:
saltdev:
- .*
- '#runner'
# Setting the job_cache to redis.
# The redis config settings are generated at the start of the docker container and
# will be written into /etc/salt/master.d/redis.conf
master_job_cache: redis
cache: redis
pki_dir: /etc/salt/pki/master/efs
The minion config looks as follows:
id: WIN-AB3GO7BJ72I
log_file: C:\salt.log
multiprocessing: False
log_level_logfile: debug
pki_dir: /conf/pki/minion
master: SaltMaster-env-vpc-test.szfegmankg.us-east-1.elasticbeanstalk.com
master_type: str
master_alive_interval: 30
open_mode: True
root_dir: c:\salt
ipc_mode: tcp
recon_default: 1000
recon_max: 199000
recon_randomize: True
In the master log files, I can see on both masters:
2017-09-05 10:06:18,118 [salt.utils.verify][DEBUG ][35] This salt-master instance has accepted 2 minion keys.
A salt-key -L on both masters yield the same result:
Accepted Keys:
WIN-AB3GO7BJ72I
WIN-EDMP9VB716B
Denied Keys:
Unaccepted Keys:
Rejected Keys:
So it looks like all is fine and everything should work. However, a test.ping is extremely flaky. Sometimes it works, but most of the time it doesnt.
Most of the time neither master gets any return from the minion and on the minion side I can see in the log that the minion never receives the message to execute 'test.ping' from the master.
Example 1:
test.ping from Master1:
root#d7383ff8f8bf:/# salt 'WIN-EDMP9VB716B' test.ping
[ERROR ] Exception raised when processing __virtual__ function for salt.loaded.int.cache.consul. Module will not be loaded: 'module' object has no attribute 'Consul'
[ERROR ] An un-handled exception was caught by salt's global exception handler:
KeyError: 'redis.ls'
Traceback (most recent call last):
File "/usr/bin/salt", line 10, in <module>
salt_main()
File "/usr/lib/python2.7/dist-packages/salt/scripts.py", line 476, in salt_main
client.run()
File "/usr/lib/python2.7/dist-packages/salt/cli/salt.py", line 173, in run
for full_ret in cmd_func(**kwargs):
File "/usr/lib/python2.7/dist-packages/salt/client/__init__.py", line 805, in cmd_cli
**kwargs):
File "/usr/lib/python2.7/dist-packages/salt/client/__init__.py", line 1597, in get_cli_event_returns
connected_minions = salt.utils.minions.CkMinions(self.opts).connected_ids()
File "/usr/lib/python2.7/dist-packages/salt/utils/minions.py", line 577, in connected_ids
search = self.cache.ls('minions')
File "/usr/lib/python2.7/dist-packages/salt/cache/__init__.py", line 244, in ls
return self.modules[fun](bank, **self._kwargs)
File "/usr/lib/python2.7/dist-packages/salt/loader.py", line 1113, in __getitem__
func = super(LazyLoader, self).__getitem__(item)
File "/usr/lib/python2.7/dist-packages/salt/utils/lazy.py", line 101, in __getitem__
raise KeyError(key)
KeyError: 'redis.ls'
Traceback (most recent call last):
File "/usr/bin/salt", line 10, in <module>
salt_main()
File "/usr/lib/python2.7/dist-packages/salt/scripts.py", line 476, in salt_main
client.run()
File "/usr/lib/python2.7/dist-packages/salt/cli/salt.py", line 173, in run
for full_ret in cmd_func(**kwargs):
File "/usr/lib/python2.7/dist-packages/salt/client/__init__.py", line 805, in cmd_cli
**kwargs):
File "/usr/lib/python2.7/dist-packages/salt/client/__init__.py", line 1597, in get_cli_event_returns
connected_minions = salt.utils.minions.CkMinions(self.opts).connected_ids()
File "/usr/lib/python2.7/dist-packages/salt/utils/minions.py", line 577, in connected_ids
search = self.cache.ls('minions')
File "/usr/lib/python2.7/dist-packages/salt/cache/__init__.py", line 244, in ls
return self.modules[fun](bank, **self._kwargs)
File "/usr/lib/python2.7/dist-packages/salt/loader.py", line 1113, in __getitem__
func = super(LazyLoader, self).__getitem__(item)
File "/usr/lib/python2.7/dist-packages/salt/utils/lazy.py", line 101, in __getitem__
raise KeyError(key)
KeyError: 'redis.ls'
I am aware that the redis error will be fixed soon https://github.com/saltstack/salt/issues/43295
Example 2:
test.ping from Master1, ~ 1 Minute after Example 1:
root#d7383ff8f8bf:/# salt 'WIN-EDMP9VB716B' test.ping
WIN-EDMP9VB716B:
True
Also during my tests, a test.ping from Master2 never succeeded.
I would like to know if there is some flaw in my setup that I am not seeing, or if Salt only works with an HA Proxy as an ELB?
Or maybe Salt doesn't work at all behind an ELB?
See https://github.com/saltstack/salt/issues/43368 for more answers.
TL;DR
Because there is no session stickyness for TCP connections, it is currently not possible to work with a saltmaster that is behind an ELB, if you use the ELB's ip/name as an entrypoint.