<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: flpslv</title>
    <description>The latest articles on Forem by flpslv (@flpslv).</description>
    <link>https://forem.com/flpslv</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F457632%2F3ed92560-2692-4472-bc05-9597a880e280.jpg</url>
      <title>Forem: flpslv</title>
      <link>https://forem.com/flpslv</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/flpslv"/>
    <language>en</language>
    <item>
      <title>Provisioning MySQL/MariaDB Vault Database Secrets Engine with Terraform</title>
      <dc:creator>flpslv</dc:creator>
      <pubDate>Tue, 30 Mar 2021 14:07:19 +0000</pubDate>
      <link>https://forem.com/flpslv/provisioning-mysql-mariadb-vault-database-secrets-engine-with-terraform-5ckd</link>
      <guid>https://forem.com/flpslv/provisioning-mysql-mariadb-vault-database-secrets-engine-with-terraform-5ckd</guid>
      <description>&lt;p&gt;The goal of this post is to provide dynamic/temporary database credentials without having to manually create and manage them all.&lt;/p&gt;

&lt;p&gt;I'm just going to start this by saying that this is just a proof of concept and best practices were not followed at all. (mainly security ones). All the procedures from this point are just simple tests with focus on easing all the side tasks just to see the whole process working.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing Containers
&lt;/h2&gt;

&lt;p&gt;We'll be using MariaDB and Vault containers, (quick) launched as specified on both projects official DockerHub pages.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Vault
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run --rm \
    --name vault \
    --cap-add=IPC_LOCK \
    -e 'VAULT_LOCAL_CONFIG={"backend": {"file": {"path": "/vault/file"}}, "default_lease_ttl": "168h", "max_lease_ttl": "720h"}' \
    -p 8200:8200 \
    -d vault

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When vault finishes starting up, we can see from the container logs the following:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You may need to set the following environment variable:&lt;/p&gt;

&lt;p&gt;$ export VAULT_ADDR='&lt;a href="http://0.0.0.0:8200"&gt;http://0.0.0.0:8200&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The unseal key and root token are displayed below in case &amp;gt;you want to&lt;br&gt;
seal/unseal the Vault or re-authenticate.&lt;/p&gt;

&lt;p&gt;Unseal Key: kSUgoPDPyBrCGWc4s93CIlMUnDLZGcxdu4doYCkWSPs=&lt;br&gt;
Root Token: s.I6TnqhrgYh8uET91FUsNvIwV&lt;/p&gt;

&lt;p&gt;Development mode should NOT be used in production &amp;gt;installations!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, we have our vault address, and the root token.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MariaDB
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run --rm \
    --name mariadb \
    -p 3306:3306 \
    -e MYSQL_ROOT_PASSWORD=mysecretpw \
    -d mariadb:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And here we have our root user and password for MariaDB.&lt;/p&gt;

&lt;p&gt;Because the root user shouldn't be used for anything, we're going to create a dedicated user for vault interactions.&lt;/p&gt;

&lt;p&gt;Login to the database using &lt;code&gt;mysql -h 127.0.0.1 -u root -p&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;and create the vault user&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;grant CREATE USER, SELECT, INSERT, UPDATE ON *.* TO 'vault'@'%' identified by 'myvaultsecretpw' WITH GRANT OPTION;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Terraform
&lt;/h2&gt;

&lt;p&gt;With all the services running and configured, it's time to take care of the terraform part.&lt;/p&gt;

&lt;p&gt;Once again, this is only a POC. All the hardcoded and weak passwords are meant for testing purposes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;provider "vault" {
    address = "http://localhost:8200"
        #Token provided from vault container log
    token = "s.I6TnqhrgYh8uET91FUsNvIwV" 
}

resource "vault_auth_backend" "userpass" {
  type = "userpass"
}

# USERS
resource "vault_generic_endpoint" "user_userro" {
  depends_on           = [vault_auth_backend.userpass]
  path                 = "auth/userpass/users/userro"
  ignore_absent_fields = true

  data_json = &amp;lt;&amp;lt;EOT
{
  "policies": ["db-ro"],
  "password": "userro"
}
EOT
}

resource "vault_generic_endpoint" "user_userrw" {
  depends_on           = [vault_auth_backend.userpass]
  path                 = "auth/userpass/users/userrw"
  ignore_absent_fields = true

  data_json = &amp;lt;&amp;lt;EOT
{
  "policies": ["db-all", "db-ro"],
  "password": "userrw"
}
EOT
}

# POLICIES
# Read-Only access policy
resource "vault_policy" "dbro" {
  name   = "db-ro"
  policy = file("policies/dbro.hcl")
}

# All permissions access policy
resource "vault_policy" "dball" {
  name   = "db-all"
  policy = file("policies/dball.hcl")
}


# DB
resource "vault_mount" "mariadb" {
  path = "mariadb"
  type = "database"
}

resource "vault_database_secret_backend_connection" "mariadb_connection" {
  backend       = vault_mount.mariadb.path
  name          = "mariadb"
  allowed_roles = ["db-ro", "db-all"]
  verify_connection = true

  mysql{
    connection_url = "{{username}}:{{password}}@tcp(192.168.11.71:3306)/"
  }

# note that I have my database address hardcoded and I'm using my lan IP, since I'm running the mysql client directly from my host and vault/mariadb are running inside containers with their ports exposed.

  data = {
    username = "vault"
    password = "myvaultsecretpw"
  } 

}

resource "vault_database_secret_backend_role" "role" {
  backend             = vault_mount.mariadb.path
  name                = "db-ro"
  db_name             = vault_database_secret_backend_connection.mariadb_connection.name
  creation_statements = ["GRANT SELECT ON *.* TO '{{name}}'@'%' IDENTIFIED BY '{{password}}';"]
}

resource "vault_database_secret_backend_role" "role-all" {
  backend             = vault_mount.mariadb.path
  name                = "db-all"
  db_name             = vault_database_secret_backend_connection.mariadb_connection.name
  creation_statements = ["GRANT ALL ON *.* TO '{{name}}'@'%' IDENTIFIED BY '{{password}}';"]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Policy files used in previous code listing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;policies/dball.hcl
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;path "mariadb/creds/db-all" {
  policy = "read"
  capabilities = ["list"]
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;policies/dbro.hcl
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;path "mariadb/creds/db-ro" {
  policy = "read"
  capabilities = ["list"]
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After this, the usual process:&lt;br&gt;
&lt;code&gt;terraform init&lt;/code&gt;&lt;br&gt;
&lt;code&gt;terraform apply&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;And we have everything ready for some testing.&lt;/p&gt;
&lt;h2&gt;
  
  
  Testing
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Testing the RO user
&lt;/h3&gt;

&lt;p&gt;Login to vault&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ vault login -method userpass username=userro
Password (will be hidden): 
Success! You are now authenticated. The token information displayed below
is already stored in the token helper. You do NOT need to run "vault login"
again. Future Vault requests will automatically use this token.
(...)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;request DB credentials&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ vault read mariadb/creds/db-ro
Key                Value
---                -----
lease_id           mariadb/creds/db-ro/uGldyp0BAa2GhUlFyrEwuIbs
lease_duration     168h
lease_renewable    true
password           8vykdcZNHp-I0pajVtoN
username           v_userpass-d_db-ro_75wxnJaL69FW4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Login to DB&lt;br&gt;
(REMEMBER: The next cmd is a really BAD PRACTICE !!! )&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ mysql -h 127.0.0.1 -u v_userpass-d_db-ro_75wxnJaL69FW4 -p'8vykdcZNHp-I0pajVtoN'

Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 101
Server version: 10.3.13-MariaDB-1:10.3.13+maria~bionic mariadb.org binary distribution

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]&amp;gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;... try to do stuff&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MariaDB [(none)]&amp;gt; create database my_database;
ERROR 1044 (42000): Access denied for user 'v_userpass-d_db-ro_75wxnJaL69FW4'@'%' to database 'my_database'

MariaDB [(none)]&amp;gt; show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| my_db              |
| mysql              |
| performance_schema |
+--------------------+
4 rows in set (0.00 sec)

MariaDB [(none)]&amp;gt; use my_db;

Database changed
MariaDB [my_db]&amp;gt; show tables;
+-----------------+
| Tables_in_my_db |
+-----------------+
| my_table        |
+-----------------+
1 row in set (0.00 sec)

MariaDB [my_db]&amp;gt; select * from my_table;
Empty set (0.00 sec)

MariaDB [my_db]&amp;gt; 

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Testing the RW user
&lt;/h3&gt;

&lt;p&gt;Login to vault&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ vault login -method userpass username=userrw
Password (will be hidden): 
Success! You are now authenticated. The token information displayed below
is already stored in the token helper. You do NOT need to run "vault login"
again. Future Vault requests will automatically use this token.
(...)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;request DB credentials&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ vault read mariadb/creds/db-all
Key                Value
---                -----
lease_id           mariadb/creds/db-all/GHRHvpuqa2ITP9tX54YHEePl
lease_duration     168h
lease_renewable    true
password           L--8mPBoprFZcaItINKI
username           v_userpass-j_db-all_DMwlhs9nGxA8
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Login to DB&lt;br&gt;
(REMEMBER AGAIN: The next cmd is a really BAD PRACTICE !!! )&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ mysql -h 127.0.0.1 -u v_userpass-j_db-all_DMwlhs9nGxA8 -p'L--8mPBoprFZcaItINKI'
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 109
Server version: 10.3.13-MariaDB-1:10.3.13+maria~bionic mariadb.org binary distribution

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]&amp;gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;... try to do stuff&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MariaDB [(none)]&amp;gt; create database my_database;
Query OK, 1 row affected (0.01 sec)

MariaDB [(none)]&amp;gt; use my_db;
Database changed

MariaDB [my_db]&amp;gt; create table the_table (i integer);
Query OK, 0 rows affected (0.03 sec)

MariaDB [my_db]&amp;gt; show tables;
+-----------------+
| Tables_in_my_db |
+-----------------+
| my_table        |
| the_table       |
+-----------------+
2 rows in set (0.00 sec)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's it. We now have the base for our MariaDB dynamic/temporary users.&lt;/p&gt;

</description>
      <category>terraform</category>
      <category>vault</category>
      <category>mariadb</category>
    </item>
    <item>
      <title>Encrypt your notes with GnuPG</title>
      <dc:creator>flpslv</dc:creator>
      <pubDate>Sat, 06 Mar 2021 02:10:53 +0000</pubDate>
      <link>https://forem.com/flpslv/encrypt-your-notes-with-gnupg-3080</link>
      <guid>https://forem.com/flpslv/encrypt-your-notes-with-gnupg-3080</guid>
      <description>&lt;p&gt;How many times did you want to put something on a text file, but didn't want to leave it there just waiting to be read by anyone?&lt;/p&gt;

&lt;p&gt;How many times you were searching for a password manager and during that search you didn't have any place to store your secrets? (more on the password manager later)&lt;/p&gt;

&lt;p&gt;There's a quick and easy way to do that: using GnuPG.&lt;/p&gt;

&lt;p&gt;GnuPG is usually installed with every linux distribution by default. And if it isn't, in case you're using a minimal image, chances are you will need to install it even to perform some basic operations with your distribution like adding new repositories (for example).&lt;/p&gt;

&lt;p&gt;Very often we come across the terms PGP, OpenPGP, GnuPG when searching for this subjects and it can be confusing sometimes.&lt;/p&gt;

&lt;p&gt;Resuming:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PGP ( Pretty Good Privacy ) was the first implementation, by Phil Zimmermann, acquired by Network Associates Inc (NAI). &lt;/li&gt;
&lt;li&gt;OpenPGP is the open standards version of PGP (which was by then owned by NAI.&lt;/li&gt;
&lt;li&gt;GnuPG is an (complete and free) implementation of the OpenPGP standard.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;More about PGP and OpenPGP can be read on the &lt;a href="https://www.openpgp.org/about/history/"&gt;History of OpenPGP&lt;/a&gt; while GnuPG information can be found on &lt;a href="https://gnupg.org/"&gt;The GNU Privacy Guard page&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To take advantage of this, make sure you have gnupg installed on your system (yes, this is debian (/based) only but it exists on other distros):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt install gnupg2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Generate your key (if you already haven't got one). It will ask your Name, Email and a Passphrase. Don't forget that despite all of the security that GPG provides, if you choose a weak passphrase, you'll be weakening all the process.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gpg2 --generate-key
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And put this little script (let's call it gvim) somewhere on your $PATH (like ~/bin/gvim for example and don't forget the chmod u+x ~/bin/gvim):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/bash
srcfile=$1
tmpfile=$(mktemp -p ${HOME})
# remember the email you used during key generation?
email="_PUT_YOUR_Email_HERE" 
if [ $? -nq 0 ]; then
    echo "error creating tempfile"
    rm $tmpfile
    exit 1
fi
gpg2 -d $scrfile &amp;gt; $tmpfile
vim $tmpfile
#this will actually wait for vim to exit

#and overwrite the original file with the new encrypted version
gpg2 -e -r $email &amp;lt; ${tmpfile} &amp;gt; $srcfile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, let's setup an easy way to read those files.&lt;br&gt;
It's simple to type gpg2 -d  but it's simpler to create an alias (and put it on your .bashrc)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;alias gcat='gpg2 -d  2&amp;gt;/dev/null'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, now, we can just use&lt;br&gt;
&lt;code&gt;gvim&lt;/code&gt; to create a new encrypted note and &lt;code&gt;gcat&lt;/code&gt; to read it anywhere.&lt;/p&gt;

&lt;p&gt;That is just a basic script. It doesn't really backup or ensure you don't lose your original data. I started to do some backups of all my notes, but that's really up to you.&lt;/p&gt;

&lt;p&gt;And last but not least, since I've mentioned the password manager, we can also use this &lt;a href="https://www.passwordstore.org/"&gt;awesome password manager&lt;/a&gt; which takes advantage of GPG and is very simple to use!&lt;/p&gt;

</description>
      <category>linux</category>
      <category>security</category>
    </item>
    <item>
      <title>Terraform AWS - Imports, Key-Pairs and Broken States</title>
      <dc:creator>flpslv</dc:creator>
      <pubDate>Thu, 04 Mar 2021 01:54:06 +0000</pubDate>
      <link>https://forem.com/flpslv/terraform-aws-imports-key-pairs-and-broken-states-4hnf</link>
      <guid>https://forem.com/flpslv/terraform-aws-imports-key-pairs-and-broken-states-4hnf</guid>
      <description>&lt;p&gt;There is nothing better than starting a new week with a full terraform infra refactoring using a clean (and shared) remote state.&lt;/p&gt;

&lt;p&gt;What do I have?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;an old and functional terraform state&lt;/li&gt;
&lt;li&gt;a new code folder better organized&lt;/li&gt;
&lt;li&gt;an empty s3 bucket to store the new state&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Starting with the clean and shared remote state:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;variable "the_profile" {}
variable "region" {}

provider "aws" {
  region = var.region
  profile = var.the_profile
}

resource "aws_s3_bucket" "state_bucket" {
  bucket = "my-uniquely-named-state-bucket"
  acl = "private"
  versioning {
    enabled = "true" # this is a must
  }

  server_side_encryption_configuration {
    rule {
      apply_server_side_encryption_by_default {
        sse_algorithm = "AES256"
      }
    }
  }

resource "aws_dynamodb_table" "terraform_state_lock" {
  name = "my-lock-table"
  read_capacity  = 1
  write_capacity = 1
  hash_key       = "LockID"
  attribute {
    name = "LockID"
    type = "S"
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Creating this init structure will then allow us to properly configure our backend:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;## Backend to keep status

provider "aws" {
  region  = var.region
  profile = var.the_profile
}

terraform {
  backend "s3" {
    bucket         = "my-uniquely-named-state-bucket"
    key            = "mystate.tfstate"
    region         = "INSERT_YOUR_REGION_HERE"
    encrypt        = "true"
    dynamodb_table = "my-lock-table"
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Things are starting to happen.&lt;/p&gt;

&lt;p&gt;After some copy+paste oriented programing, I managed to place all my files from the old structure into the new and I'm ready do run my first plan.&lt;/p&gt;

&lt;p&gt;And terraform said:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Plan: WAY TOO MANY to add, 0 to change, 0 to destroy.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;( ok, it didn't say that, but that's what I read )&lt;/p&gt;

&lt;p&gt;Adding the VPC, the Subnets, the Routing Tables, the Security Groups, the Instances and all the other "direct resources" was fairly easy. Nothing that a few queries here and there and some &lt;code&gt;terraform import TERRAFORM_RESOURCE_NAME AWS_ID&lt;/code&gt;&lt;br&gt;
didn't handle. And the easiest part was done.&lt;/p&gt;
&lt;h2&gt;
  
  
  Enter the Security Group Rules
&lt;/h2&gt;

&lt;p&gt;This is where things started to get interesting.&lt;br&gt;
Quoting directly from terraform &lt;a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule"&gt;aws_security_group_rule&lt;/a&gt; page,&lt;br&gt;
&lt;code&gt;Security Group Rules can be imported using the security_group_id, type, protocol, from_port, to_port, and source(s)/destination(s) (e.g. cidr_block) separated by underscores (_). All parts are required.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Luckily I had access to my previous functional terraform state. And with a little bit of python I could find and extract the required ID for each missing security group rule.&lt;/p&gt;

&lt;p&gt;So, once more the&lt;br&gt;
&lt;code&gt;terraform import aws_security_group_rule.sg_allow_stuff sg-001122334455_ingress_tcp_8080_8080_sg-001122334455&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Thing is, the plan continued to show things like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-/+ resource "aws_security_group_rule" "sg_allow_stuff" {
      - cidr_blocks              = [] -&amp;gt; null
      ~ id                       = "sgrule-12345678" -&amp;gt; (known after apply)
      - ipv6_cidr_blocks         = [] -&amp;gt; null
      - prefix_list_ids          = [] -&amp;gt; null
      ~ self                     = false -&amp;gt; true # forces replacement
      ~ source_security_group_id = "sg-001122334455" -&amp;gt; (known after apply)
        # (5 unchanged attributes hidden)
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;when I noticed that line&lt;br&gt;
&lt;code&gt;self = false -&amp;gt; true # forces replacement&lt;/code&gt;&lt;br&gt;
and the fact that the source and destiny security group IDs were the same.&lt;/p&gt;

&lt;p&gt;So, the &lt;strong&gt;&lt;em&gt;self&lt;/em&gt;&lt;/strong&gt; was the issue. No problem, just add it at the end of the AWS_ID part on the import command:&lt;br&gt;
&lt;code&gt;terraform import aws_security_group_rule.sg_allow_stuff sg-001122334455_ingress_tcp_8080_8080_sg-001122334455_self&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;And it imported!&lt;/p&gt;
&lt;h2&gt;
  
  
  And the stubborn Key
&lt;/h2&gt;

&lt;p&gt;Two minutes (to midnight) after and all the security group rules were added into the new state.&lt;/p&gt;

&lt;p&gt;There was only this aws_key_pair missing.&lt;br&gt;
Ok! Let's go!&lt;br&gt;
&lt;code&gt;terraform import aws_key_pair.auth thekeyname&lt;/code&gt;&lt;br&gt;
Ok! It imported as all the other resources! Nothing new so far...&lt;/p&gt;

&lt;p&gt;But, the next apply, THAT key was still:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  # aws_key_pair.auth will be created
  + resource "aws_key_pair" "auth" {
      + arn         = (known after apply)
      + fingerprint = (known after apply)
      + id          = (known after apply)
      + key_name    = "thekeyname"
      + key_pair_id = (known after apply)
      + public_key  = "#### EMPTY"
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Oh, that "#### EMPTY". I forgot to add the resource on my side.&lt;br&gt;
A few keystrokes after (now with the correct key), the same:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  # aws_key_pair.auth will be created
  + resource "aws_key_pair" "auth" {
      + arn         = (known after apply)
      + fingerprint = (known after apply)
      + id          = (known after apply)
      + key_name    = "thekeyname"
      + key_pair_id = (known after apply)
      + public_key  = "ssh-rsa yaddayaddayadda..."
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hello google my old friend :)&lt;br&gt;
&lt;a href="https://github.com/hashicorp/terraform-provider-aws/issues/1092"&gt;Turns out I wasn't the first to hit this wall&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ok, so let's try one of the suggested solutions there.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Download the new state from S3&lt;/li&gt;
&lt;li&gt;Edit the state, search for the entry corresponding to the key&lt;/li&gt;
&lt;li&gt;Enter the public key manually on the &lt;code&gt;public_key&lt;/code&gt; field (not forgetting the quotes)&lt;/li&gt;
&lt;li&gt;Save the state&lt;/li&gt;
&lt;li&gt;Upload it and ...&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;!!!RUN TERRAFORM!!! ( !!! RUN FOR YOUR LIVES !!! )&lt;/p&gt;

&lt;p&gt;Sadly, Terraform says NO! :(&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Error: Error loading state: state data in S3 does not have the expected content.

This may be caused by unusually long delays in S3 processing a previous state
update.  Please wait for a minute or two and try again. If this problem
persists, and neither S3 nor DynamoDB are experiencing an outage, you may need
to manually verify the remote state and update the Digest value stored in the
DynamoDB table to the following value: 5d3a61408eb4ba89aeaf09818561d0a7
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Like anyone in trouble, I just focused on the first part of the message. "Things were looking bad" I thought. On top of that, I was so confident that I didn't even backup the state before altering it. &lt;br&gt;
BUT ... Bucket versioning to the rescue!&lt;/p&gt;

&lt;p&gt;&lt;code&gt;aws s3api get-object --bucket my-uniquely-named-state-bucket --key mystate.tfstate --version abcdversionreferencehere mystate.tfstate&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Of course this didn't solve the problem (as I figured out after a second upload). I decided to calm down and read everything.&lt;/p&gt;

&lt;p&gt;DynamoDB Digest? Interesting. So, there was no big problem after all. Turns out the tfstate md5 digest was stored on dynamoDB and there was a couple of missing steps on my procedure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Download the new state from S3&lt;/li&gt;
&lt;li&gt;Edit the state, search for the entry corresponding to the key&lt;/li&gt;
&lt;li&gt;Enter the public key manually on the &lt;code&gt;public_key&lt;/code&gt; field (not forgetting the quotes)&lt;/li&gt;
&lt;li&gt;Save the state&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;get the md5 sum of the state&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;update the md5 digest on the DynamoDB terraform_state_lock table&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Upload the modified state&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And everything worked like it was supposed to!&lt;/p&gt;

&lt;p&gt;What did I learn?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;READ everything. Not just the begining
&lt;/li&gt;
&lt;li&gt;Always BACKUP (or Enable versioning when possible)&lt;/li&gt;
&lt;li&gt;Google is your friend. (nothing really new here)&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>terraform</category>
      <category>aws</category>
    </item>
    <item>
      <title>Running WineHQ inside a docker container</title>
      <dc:creator>flpslv</dc:creator>
      <pubDate>Thu, 24 Sep 2020 10:00:17 +0000</pubDate>
      <link>https://forem.com/flpslv/running-winehq-inside-a-docker-container-52ej</link>
      <guid>https://forem.com/flpslv/running-winehq-inside-a-docker-container-52ej</guid>
      <description>&lt;p&gt;(Before I waste any of your time, let me start by warning that this post was done using the nVidia gpu that's on my system. Unfortunately I don't have (yet) the means (nor time) to properly test this with an AMD or even Intel GPU.)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F1jehrsxwyww4t0kfg85a.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F1jehrsxwyww4t0kfg85a.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Well ...&lt;br&gt;
Nowadays this isn't exactly true...&lt;br&gt;
Nor this solution is the best.&lt;br&gt;
But as I said in my profile, I'm just curious.&lt;/p&gt;

&lt;p&gt;Things have evolved, tools like lutris or even steam's proton are providing easier and faster ways of playing games that do not have native linux ports. &lt;/p&gt;

&lt;p&gt;I have tried both and things just work. It's a fact. And I was able to play the ( supported ) games I wanted without big effort: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;With &lt;a href="https://lutris.net/" rel="noopener noreferrer"&gt;Lutris&lt;/a&gt;, I just had to go to the site and pull the pre-configured installer for the game I wanted and let it work it's magic.&lt;/li&gt;
&lt;li&gt;With &lt;a href="https://store.steampowered.com/" rel="noopener noreferrer"&gt;Steam&lt;/a&gt; &lt;a href="https://github.com/ValveSoftware/Proton" rel="noopener noreferrer"&gt;Proton&lt;/a&gt;, I just had to download the game and play it.&lt;/li&gt;
&lt;li&gt;With &lt;a href="https://www.winehq.org/" rel="noopener noreferrer"&gt;Wine&lt;/a&gt; itself, either installed by my distro package manager or compiled from source.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of those, as I stated before just work perfectly (one way or another). But curiosity was still nagging: "Can I just have a container with all that stuff installed and not have all those dependencies dangling on my system?"&lt;/p&gt;

&lt;p&gt;In fact, that question always comes back to me once in a while, when I think about how many stuff I have installed on my system and how many I really need on a daily basis. Even further, what will I miss when I change or need to reinstall my distro.&lt;/p&gt;

&lt;p&gt;With that in mind, I started to experiment with containers. Even if only to test newer wine versions on a more or less clean way, because I've already upgraded to a newer version that unfortunately was broken, and had to reinstall the previous working version packages.&lt;/p&gt;

&lt;p&gt;So, I decided to build things up from a Ubuntu Focal container and split in two containers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;My base container based on Ubuntu having only the nVidia drivers installed&lt;/li&gt;
&lt;li&gt;My actual wine container with all the dependencies for the games.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I went for this approach since gpu drivers don't come out that often (unfortunately) and I can also have a base image to work with.&lt;/p&gt;

&lt;p&gt;Before going into more detail, if you notice anything unusual with the Dockerfiles is because this build system is prepared to be &lt;a href="https://dev.to/flpslv/using-makefiles-to-build-and-publish-docker-containers-7c8"&gt;used with Makefiles&lt;/a&gt;. But they also can be built normally with the traditional &lt;code&gt;docker build&lt;/code&gt; cmd. The defaults can be overridden with --build-arg flags.&lt;/p&gt;

&lt;p&gt;Also, &lt;strong&gt;&lt;em&gt;make sure the driver version you have installed on your host are the same as the drivers installed inside the container&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Base container
&lt;/h4&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

ARG UBUNTU_VERSION=focal
ARG NVIDIA_DRIVER_VERSION=450
FROM ubuntu:$UBUNTU_VERSION

ARG UBUNTU_VERSION
ARG NVIDIA_DRIVER_VERSION

ENV DEBIAN_FRONTEND=noninteractive
ENV UBUNTU_VERSION=$UBUNTU_VERSION
ENV NVIDIA_DRIVER_VERSION=$NVIDIA_DRIVER_VERSION

ENV PKGNV="nvidia-driver-${NVIDIA_DRIVER_VERSION} libnvidia-gl-${NVIDIA_DRIVER_VERSION}:i386"
ENV PKGVK="libvulkan1 libvulkan1:i386 vulkan-tools vulkan-utils"


RUN     dpkg --add-architecture i386 &amp;amp;&amp;amp; \
    apt update &amp;amp;&amp;amp; \
    apt install -y gnupg2 apt-transport-https curl 

RUN apt install -y $PKGNV $PKGVK



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;So, this is the first container, based on a ubuntu focal version and nvidia drivers 450 (by default), vulkan and a few base tools to be used later. I will refer to it for the next steps as &lt;code&gt;ubuntu-nvidia-vlk:focal&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Wine container
&lt;/h4&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

FROM ubuntu-nvidia-vlk:focal

ARG WVERSION="5.17"
ARG WTVERSION="20200412"

ENV WINE_VERSION="${WVERSION}"
ENV PKG_WINE_VERSION="${WVERSION}~${UBUNTU_VERSION}"
ENV WINE_TRICKS_VERSION="${WTVERSION}"

RUN curl -s https://dl.winehq.org/wine-builds/winehq.key | apt-key add - &amp;amp;&amp;amp; \
    echo "deb https://dl.winehq.org/wine-builds/ubuntu/ ${UBUNTU_VERSION} main" | tee /etc/apt/sources.list.d/wine.list &amp;amp;&amp;amp; \
    apt update &amp;amp;&amp;amp; \
    apt install -y winbind cabextract wget fonts-wine ttf-mscorefonts-installer\
        winehq-staging=$PKG_WINE_VERSION \
        wine-staging=$PKG_WINE_VERSION \
        wine-staging-i386=$PKG_WINE_VERSION \
        wine-staging-amd64=$PKG_WINE_VERSION

ADD https://github.com/Winetricks/winetricks/archive/${WINE_TRICKS_VERSION}.zip /tmp/wt.zip 
RUN unzip /tmp/wt.zip -d /tmp/ &amp;amp;&amp;amp; \
    cp /tmp/winetricks-${WINE_TRICKS_VERSION}/src/winetricks /usr/local/bin &amp;amp;&amp;amp; \
    rm -Rf /tmp/*



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;And we can call this our winehq:5.17 container. &lt;/p&gt;

&lt;p&gt;So, we have a base container and a wine container. &lt;br&gt;
Since most of the games will ask for &lt;code&gt;winbind&lt;/code&gt; and &lt;code&gt;cabextract&lt;/code&gt; I've decided to put those together with wine. Also, some font packages since they're used a lot by launchers/loaders.&lt;br&gt;
I guess I could have another stage just for those needed packages, but I didn't have the time yet to figure out the best stage to put them.&lt;br&gt;
So now we only need to create a script to use the containers to avoid having to memorize a huge command line.&lt;/p&gt;

&lt;p&gt;At this point, we could also add &lt;a href="https://github.com/doitsujin/dxvk" rel="noopener noreferrer"&gt;dxvk&lt;/a&gt; to our container by adding this lines to the dockerfile&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

ARG DXVKVERSION="1.7.1"
ENV DXVK_VERSION="${DXVK_VERSION}"
ADD https://github.com/doitsujin/dxvk/releases/download/v${DXVK_VERSION}/dxvk-${DXVK_VERSION}.tar.gz /tmp/dxvk.tar.gz 


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;... but DXVK can also be installed by winetricks. So, I'll just go with winetricks method for now.&lt;/p&gt;

&lt;p&gt;We can add this script to one of the PATH directories so we can start the container at any time.&lt;/p&gt;

&lt;p&gt;Also, it's just a personal preference to have all the versions as environment variables on my container, so I can quickly check them any time I need.&lt;/p&gt;

&lt;p&gt;It will create a temporary folder on your $HOME/tmp path and use it as $HOME inside the container. Also, the current path which will also be the WINEPREFIX will be placed inside the container on $HOME/game.&lt;/p&gt;

&lt;p&gt;I had to do it this way, because the .Xauthority file will be mounted in the home dir and since it's a volume two things could happen:&lt;br&gt;
1 - if I made the WINEPREFIX my home dir, the .Xauthority file would end up being copied to that location on the host.&lt;br&gt;
2 - if the home dir didn't exist, it would be created by the user &lt;code&gt;root&lt;/code&gt; (the container default user) which could lead to lack of permissions for some apps that use the home dir as default location to write theyr own files ( winetricks, for example).&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

#!/bin/bash

curdir="$(pwd)"
vhome="${HOME}/tmp/.winestorage"

if [ ! -d "$vhome" ]; then
    echo "creating $vhome"
    mkdir -p $vhome
fi

docker run --rm \
    --name wine \
    -u $(id -u):$(id -g) \
    -e DISPLAY \
    -e WINEPREFIX=/wine/game \
    -v /tmp/.X11-unix:/tmp/.X11-unix \
    -e PULSE_SERVER=unix:/pulse \
    -e HOME=/wine \
    -v $HOME/.Xauthority:/wine/.Xauthority \
    -v /run/user/$(id -u)/pulse/native:/pulse \
    --device /dev/nvidia0:/dev/nvidia0 \
    --device /dev/nvidiactl:/dev/nvidiactl \
    --device /dev/nvidia-uvm:/dev/nvidia-uvm \
    --device /dev/nvidia-uvm-tools:/dev/nvidia-uvm-tools \
    --device /dev/nvidia-modeset:/dev/nvidia-modeset \
    -v ${vhome}:/wine \
    -v ${curdir}:/wine/game \
    -ti \
    winehq:5.17 \
    bash


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;There are several considerations to this script:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;it will be removed after termination &lt;code&gt;--rm&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;it will map my user and group inside the container &lt;code&gt;-u $(id -u):$(id -g)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;it will set the WINEPREFIX env to /wine/game &lt;code&gt;-e WINEPREFIX=/wine/game&lt;/code&gt; and set my HOME to /wine &lt;code&gt;-e HOME=/wine&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;it will mount the directory containing the X11 sockets inside the container &lt;code&gt;-v /tmp/.X11-unix:/tmp/.X11-unix&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;since I'm using pulesaudio it will define the socket path &lt;code&gt;-e PULSE_SERVER=unix:/pulse&lt;/code&gt; and it will place my actual socket inside the container &lt;code&gt;-v /run/user/$(id -u)/pulse/native:/pulse&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;it will mount my .Xauthority file on the user's home directory &lt;code&gt;-v $HOME/.Xauthority:/wine/.Xauthority&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;add all my devices corresponding to the nVidia gpu&lt;/li&gt;
&lt;li&gt;and finally mount the home and game paths in the container&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We can also extend this script to pass extra wine variables to the container. &lt;/p&gt;

&lt;p&gt;Now, inside the container we can just go directly to &lt;code&gt;/wine/game&lt;/code&gt; and start installing or playing what we want to run.&lt;/p&gt;

&lt;p&gt;When trying to install something that needs extra packages installed, there is also the possibility of opening a new shell, enter the container as root and install what we need just by running &lt;code&gt;docker exec -u root -ti wine bash&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Using wine isn't really the target of this post, but there is enough information around the internet to help with that. And having winetricks installed is also a nice aid to configure prefixes.&lt;br&gt;
One of the motives I had, using that directory structure (and the $vhome path) was also to try to maintain some cache for winetricks downloads.&lt;/p&gt;

&lt;p&gt;I've tried this method to launch Battle.net and try a couple of games which worked surprisingly well.&lt;/p&gt;

&lt;p&gt;I was also able to run Epic Games Store, but unfortunately had no luck when trying to play the few games I have there. I guess some things were missing on my prefix. &lt;/p&gt;

&lt;p&gt;And finally, was able to install Wargaming's Game Center and play a few rounds of world of tanks.&lt;/p&gt;

&lt;p&gt;At this point, most of the needed work is just figuring out which dependencies we need in our prefix and which wine libraries we need to override. Lutris installation scripts are nice to look for more information on a given game.&lt;br&gt;
Some errors still occur, but the wine debug messages can also help to trace some problems and find the possible missing packages we might need to install.&lt;/p&gt;

&lt;h2&gt;
  
  
  Security Concerns
&lt;/h2&gt;

&lt;p&gt;I'm not going to dive deep into this approach security flaws.&lt;br&gt;
Ari Kalfus already did it &lt;strong&gt;very well&lt;/strong&gt; on his post &lt;a href="https://dev.to/artis3n/running-a-graphical-application-from-a-docker-container-simply-and-securely-2m2b"&gt;Running a Graphical Application from a Docker Container - Simply and Securely&lt;/a&gt;. It's worth the read even if you're not thinking on running any GUI applications.&lt;/p&gt;

&lt;p&gt;So, let's just try to tweak a bit our launcher script to address some of those valid points:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

#!/bin/bash

curdir="$(pwd)"
vhome="${HOME}/tmp/.winestorage"

if [ ! -d "$vhome" ]; then
    echo "creating $vhome"
    mkdir -p $vhome
fi

docker run --rm \
    --cap-drop=all \
    --name wine \
    -u $(id -u):$(id -g) \
    -e DISPLAY \
    -e WINEPREFIX=/wine/game \
    -v /tmp/.X11-unix:/tmp/.X11-unix:ro \
    -e PULSE_SERVER=unix:/pulse \
    -e HOME=/wine \
    -v $HOME/.Xauthority:/wine/.Xauthority:ro \
    -v /run/user/$(id -u)/pulse/native:/pulse \
    --device /dev/nvidia0:/dev/nvidia0 \
    --device /dev/nvidiactl:/dev/nvidiactl \
    --device /dev/nvidia-uvm:/dev/nvidia-uvm \
    --device /dev/nvidia-uvm-tools:/dev/nvidia-uvm-tools \
    --device /dev/nvidia-modeset:/dev/nvidia-modeset \
    -v ${vhome}:/wine \
    -v ${curdir}:/wine/game \
    -ti \
    winehq:5.17 \
    bash


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Bear in mind that one of the things that stops working when we add the &lt;code&gt;--cap-drop=all&lt;/code&gt; is the possibility to enter the container as &lt;code&gt;root&lt;/code&gt; and change anything on the container system. &lt;/p&gt;

&lt;p&gt;Of course there are easier ways to play games on linux, but having this working is a nice thing for me, so I can get rid of many unwanted installed packages on my host system.&lt;/p&gt;

&lt;p&gt;I could improve this post on trying to get this working on AMD or Intel graphics, but it's something I won't be able to do for now.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>gaming</category>
      <category>linux</category>
    </item>
    <item>
      <title>What's your favorite minimal linux distro?</title>
      <dc:creator>flpslv</dc:creator>
      <pubDate>Thu, 17 Sep 2020 21:45:47 +0000</pubDate>
      <link>https://forem.com/flpslv/what-s-your-favorite-minimal-linux-distro-fkh</link>
      <guid>https://forem.com/flpslv/what-s-your-favorite-minimal-linux-distro-fkh</guid>
      <description>&lt;p&gt;What is your favorite minimal distro, so you can just install a base system (no DE, no X, nothing from start) and build it up from there?&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>linux</category>
    </item>
    <item>
      <title>Bypassing AWS Cli profile to use IAM Roles</title>
      <dc:creator>flpslv</dc:creator>
      <pubDate>Fri, 28 Aug 2020 23:38:15 +0000</pubDate>
      <link>https://forem.com/flpslv/bypassing-aws-cli-profile-to-use-iam-roles-54eg</link>
      <guid>https://forem.com/flpslv/bypassing-aws-cli-profile-to-use-iam-roles-54eg</guid>
      <description>&lt;p&gt;While trying to upgrade some legacy AWS instances which were already configured and working, I just needed to start configuring and using EC2 IAM Roles.&lt;/p&gt;

&lt;p&gt;I just attached a simple (and permissive) EC2 role to my instance to see what I could do with it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "s3:List*",
                "s3:Get*"
            ],
            "Effect": "Allow",
            "Resource": "*"
        }
    ]
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;and started to furiously type my copy command&lt;br&gt;
&lt;code&gt;aws s3 cp s3://my-own-and-only-bucket/file .&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Problem was that someone had already configured some profiles for the aws cli, even worst, the default profile was also configured and it was being used for some random operation I wasn't able to find out. &lt;/p&gt;

&lt;p&gt;Checking &lt;a href="https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html"&gt;AWS Documentation&lt;/a&gt; on configuration precedence&lt;/p&gt;

&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Command line options&lt;/strong&gt; – Overrides settings in any other location. You can specify --region, --output, and --profile as parameters on the command line.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Environment variables&lt;/strong&gt; &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;*&lt;em&gt;CLI credentials file *&lt;/em&gt;( ~/.aws/credentials on Linux or macOS, or at C:\Users\USERNAME.aws\credentials on Windows.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;CLI configuration file&lt;/strong&gt; ( ~/.aws/config on Linux or macOS, or at C:\Users\USERNAME.aws\config on Windows.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Container credentials&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Instance profile credentials&lt;/strong&gt; – You can associate an IAM role with each of your Amazon Elastic Compute Cloud (Amazon EC2) instances. &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;

&lt;p&gt;And as the default profile didn't have all the needed S3 permissions I kept hitting the annoying 403 Forbidden. &lt;/p&gt;

&lt;p&gt;It really crossed my mind first to delete the credentials file and second to rename the default profile to something else. I just had no way to know what process would break next.&lt;/p&gt;

&lt;p&gt;So, to &lt;em&gt;bypass&lt;/em&gt; the credentials file default profile and make the aws cli use the IAM Role, all I needed to do was to create a dummy almost empty profile setting the output ( for example) ...&lt;/p&gt;

&lt;p&gt;&lt;code&gt;vim ~/.aws/credentials&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[profile dummy]
output = json
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;... and force my copy command to use that profile&lt;br&gt;
&lt;code&gt;aws s3 cp s3://my-own-and-only-bucket/file . --profile dummy&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Turns out that without the access keys on that profile, it ended up using the next available credentials: the IAM role.&lt;/p&gt;

&lt;p&gt;Now I could resume with the upgrade ... as soon as I found out what was using those credentials. &lt;/p&gt;

</description>
      <category>aws</category>
    </item>
    <item>
      <title>Chroming Incognito</title>
      <dc:creator>flpslv</dc:creator>
      <pubDate>Wed, 26 Aug 2020 22:58:58 +0000</pubDate>
      <link>https://forem.com/flpslv/chroming-incognito-33bf</link>
      <guid>https://forem.com/flpslv/chroming-incognito-33bf</guid>
      <description>&lt;p&gt;The subject has been brought up frequently from time to time, but I would like to ask "Do we really browse incognito?"&lt;/p&gt;

&lt;p&gt;I mean, there are lots of warning guides teaching people about the Incognito mode and how to achieve it across several browsers, but is it really incognito? How far incognito does it go?&lt;/p&gt;

&lt;p&gt;The other day I was trying to &lt;em&gt;Incognito&lt;/em&gt; some browsing session due to my musical guilty pleasures (and not wanting to get recommendations based on those) when I thought:&lt;br&gt;
Hey, How much &lt;em&gt;Incognito&lt;/em&gt; is this, if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It knows some of my history ?&lt;/li&gt;
&lt;li&gt;It still shares the same data path as my regular mode browser ?&lt;/li&gt;
&lt;li&gt;I open a second &lt;em&gt;Incognito&lt;/em&gt; and it has my sessions from the first one ?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ok, maybe &lt;em&gt;Incognito&lt;/em&gt; isn't something we can fully achieve, there will be always some loophole but at least I wasn't going down that easily.&lt;/p&gt;

&lt;p&gt;Just added this script to one of my path folders, and some of those thoughts just got some answers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt; #!/bin/bash

google-chrome --incognito --user-data-dir=$(mktemp -d /tmp/x.XXXXXXX) 2&amp;gt;/dev/null &amp;amp;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;( and giving it execution permission of course )&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It isn't perfect.&lt;br&gt;
Along the day, my /tmp folder gets filled with these chrome data dirs, but it all goes away eventually (automatically with a reboot/power off or manually by simply removing them). Or I could just not run it in background and remove the folder after that. There's always room for improvement somewhere.&lt;/p&gt;

&lt;p&gt;Now, this doesn't hold any guarantee that at some point, things stop being &lt;em&gt;Incognito&lt;/em&gt;. But at least from what I've seen, it just creates another local degree of separation.&lt;/p&gt;

&lt;p&gt;(I've only tested this with Chrome. I'm sure it must work with other browsers also)&lt;/p&gt;

&lt;p&gt;Or you could just try to run the browser inside a container!!! &lt;/p&gt;

</description>
      <category>chrome</category>
      <category>incognito</category>
    </item>
    <item>
      <title>Using Makefiles to build and publish (docker) containers</title>
      <dc:creator>flpslv</dc:creator>
      <pubDate>Tue, 25 Aug 2020 08:21:34 +0000</pubDate>
      <link>https://forem.com/flpslv/using-makefiles-to-build-and-publish-docker-containers-7c8</link>
      <guid>https://forem.com/flpslv/using-makefiles-to-build-and-publish-docker-containers-7c8</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_6WOooUj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ian08d74e3n2c901wji8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_6WOooUj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ian08d74e3n2c901wji8.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;There are more things in make and dockerfiles, Horatio,&lt;br&gt;
Than are explained of in your documentation.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;First of all, let's start this brief train of thought by acknowledging that despite docker is a synonym of containers, the other way around isn't true.&lt;/p&gt;

&lt;p&gt;We could dwell on the origins of containers, but there are tons of much more valid articles out there than anything I could begin to try to explain here. &lt;/p&gt;

&lt;p&gt;I'm assuming that containers, docker and dockerfiles aren't new terms for anyone reading this, but if that's the case then you can probably start by checking &lt;a href="https://www.ibm.com/cloud/learn/containers"&gt;containers&lt;/a&gt;, &lt;a href="https://www.docker.com/"&gt;docker&lt;/a&gt; and [dockerfile].(&lt;a href="https://docs.docker.com/engine/reference/builder/"&gt;https://docs.docker.com/engine/reference/builder/&lt;/a&gt;)&lt;/p&gt;
&lt;h2&gt;
  
  
  Motivation
&lt;/h2&gt;

&lt;p&gt;Usually, when I'm writing a &lt;em&gt;dockerfile&lt;/em&gt; to ensure I'll never forget the needed steps to successfully build this or that container I always find myself looking at all those &lt;em&gt;hardcoded&lt;/em&gt; version numbers and other things that could really fit in the definition of variables but for some reason end up for (commit&amp;amp;push) posterity.&lt;/p&gt;

&lt;p&gt;By now you must be thinking, using some nice words, that &lt;strong&gt;&lt;em&gt;this guy should really learn how to work with docker build arguments and stop wasting my time&lt;/em&gt;&lt;/strong&gt;, but there is no denying it always ends up on memorizing all the arguments, which never happens.&lt;/p&gt;
&lt;h2&gt;
  
  
  Dockerfile
&lt;/h2&gt;
&lt;h3&gt;
  
  
  First step: meet &lt;a href="https://kubernetes.io/docs/tasks/tools/install-kubectl/"&gt;kubectl&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;What kubectl is or does is out of scope for this post. We're only using it out as an example, because it was the first thing that popped into my mind.&lt;br&gt;
Let's build a small container for kubectl:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM alpine:3.12

ADD https://storage.googleapis.com/kubernetes-release/release/v1.18.0/bin/linux/amd64/kubectl /usr/local/bin/kubectl

RUN chmod +x /usr/local/bin/kubectl

ENTRYPOINT ["kubectl"]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;As you can see, in just a small dockerfile, 2 hardcoded versions just jump into eyesight:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the alpine version itself&lt;/li&gt;
&lt;li&gt;the kubectl version&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Second step: some adjustments
&lt;/h3&gt;

&lt;p&gt;Luckily Dockerfile syntax (evolving or not through the years) allows us to do some nice modifications:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ARG ALP_VER=3.12
FROM alpine:$ALP_VER

ARG KCTL_VER=1.18.0

ADD https://storage.googleapis.com/kubernetes-release/release/v${KCTL_VER}/bin/linux/amd64/kubectl /usr/local/bin/kubectl

RUN chmod +x /usr/local/bin/kubectl

ENTRYPOINT ["kubectl"]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;So now, not only I can modify those two versions as I please, as I can build the image without passing any argument (which will build it with the default versions).&lt;/p&gt;

&lt;p&gt;Of course I could just go and issue a docker build command that simply works with that Dockerfile and shows how I can manipulate those arguments &lt;br&gt;
&lt;code&gt;docker build --build-arg ALP_VER=3.11 --build-arg KCTL_VER=1.18.0 -t my_kubectl:1.18.0 .&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But that just wasn't enough for me. It's not that hard, but then I'd have to remember the argument names for several dockerfiles.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Makefile
&lt;/h2&gt;

&lt;p&gt;I decided I'd only settle for a simpler syntax. &lt;br&gt;
Not only something that didn't make me type those long commands but at the same time, something a little nicer than a simple (and ugly) bash script.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Now I can just build using whatever versions I want:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;default &lt;code&gt;make build&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;another alpine version &lt;code&gt;make build alpver=3.11&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;another kubectl version &lt;code&gt;make build kctlver=1.17.0&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;both modified versions &lt;code&gt;make build alpver=3.11 kctlver=1.17.0&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I can build and push into the configured registry&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;default &lt;code&gt;make&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;another alpine version &lt;code&gt;make alpver=3.11&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;... and so on ...&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Or I can easily check ( without any file opening ) which things I can change on that image&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;make help&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Surely there are other things that got hardcoded somewhere, like the repository name, but this is only the beginning.&lt;/p&gt;

&lt;p&gt;Of course this isn't THE WAY nor THE ONLY WAY. I'm not that naive. I'm sure many other options are available to do it and I'd like to know about them in the comment area.&lt;/p&gt;

</description>
      <category>docker</category>
    </item>
  </channel>
</rss>
