Adds link to maven central

Adds link to maven central

= Provides a JavaEE Event <--> RabbitMQ bridge.
Patrick Reinhart <https://github.com/reinhapa[@reinhapa]>
:project-name: rabbitmq-cdi
:group-name: net.reini
:project-full-path: reinhapa/{project-name}
:github-branch: master

image:https://img.shields.io/badge/license-MIT-blue.svg["MIT License", link="https://github.com/{project-full-path}/blob/{github-branch}/LICENSE"]
image:https://img.shields.io/badge/Java-8-blue.svg["Supported Versions", link="https://travis-ci.org/{project-full-path}"]
image:https://img.shields.io/badge/Java-9-blue.svg["Supported Versions", link="https://travis-ci.org/{project-full-path}"]
image:https://img.shields.io/badge/Java-10-blue.svg["Supported Versions", link="https://travis-ci.org/{project-full-path}"]
image:https://img.shields.io/badge/Java-11-blue.svg["Supported Versions", link="https://travis-ci.org/{project-full-path}"]
image:https://img.shields.io/badge/Java-12-blue.svg["Supported Versions", link="https://travis-ci.org/{project-full-path}"]
image:https://img.shields.io/github/release/{project-full-path}.svg["Release", link="https://github.com/{project-full-path}"]
image:https://img.shields.io/maven-central/v/{group-name}/{project-name}.svg?label=Maven%20Central["Maven Central", link="https://search.maven.org/search?q=g:%22{group-name}%22%20AND%20a:%22{project-name}%22"]
image:https://img.shields.io/travis/{project-full-path}/{github-branch}.svg["Build Status", link="https://travis-ci.org/{project-full-path}"]
image:https://img.shields.io/codecov/c/github/{project-full-path}/{github-branch}.svg["Code Coverage", link="https://codecov.io/github/{project-full-path}?branch={github-branch}"]
image:https://codecov.io/github/{project-full-path}/branch.svg?branch={github-branch}[codecov.io]

This project contains all needed classes to bind JavaEE enterprise events to a
RabbitMQ exchange for outgoing events. Inbound events can also be bound to the
respective queues and will be handed over to all JavaEE event observers.

The RabbitMQ message content is done via JSON serialization of a Java Bean
compatible PoJo object and vice versa.

== Usage example

First you need to define event objects using standard Java Bean syntax:

[source,java]
----
public class EventOne {
  private boolean enabled;

  public boolean isEnabled() {
    return enabled;
  }

  public void setEnabled(boolean enabled) {
    this.enabled = enabled;
  }
}

public class EventTwo {
  private String value;

  public String getValue() {
    return value;
  }

  public void setValue(String value) {
    this.value = value;
  }
}
----

As second step you have to define the bindings:

[source,java]
----
@Dependent
public class RabbitBinder extends EventBinder {
  @Override
  protected void bindEvents() {

    ExchangeDeclaration testExchangeOne = declarerFactory()
    .createExchangeDeclaration("test.exchange.one")
      .withExchangeType(BuiltinExchangeType.DIRECT)
      .withAutoDelete(false)
      .withDurable(false); // <1>

    QueueDeclaration testQueue = declarerFactory()
    .createQueueDeclaration("test.queue")
      .withAutoDelete(false)
      .withDurable(false)
      .withExclusiveAccess(false); // <2>

    bind(EventOne.class)
      .toExchange("test.exchange.one");
      .withDeclaration(testExchangeOne) // <3>
    bind(EventOne.class)
      .toExchange("test.exchange.two")
      .withRoutingKey("test.key")
      .withEncoder(new MyCustomEncoder()); // <4>

    bind(EventTwo.class)
      .toQueue("test.queue");
    bind(EventTwo.class)
      .toQueue("test.queue")
      .withDecoder(new MyCustomDecoder())
      .withDeclaration(testQueue)
      .autoAck(); // <5>
  }
}
----
<1> Create exchange declaration for exchange with name 'test.exchange.one' and type 'direct'
<2> Creates queue declaration for queue with name 'test.queue'
<3> Uses an empty routing key for exchange 'test.exchange.one' and adds exchange declaration for this publisher
<4> Specifies a custom event encoder
<5> Specifies a custom event decoder, enables auto acknowledge and adds queue declaration for this consumer

Note to declarations:

Created declarations are not automatically declared on broker side.
For each consumer/producer own channels exist because of that reason it is necessary to
add the declaration needed to a binding via .withDeclaration(..)
Only these declarations are applied for this consumer/producer

As last step you need to initialize the binder either in a singleton
startup bean or servlet after having also configured the connection settings:

[source,java]
----
@Singleton
@Startup
public class BindingInitializer {
  @Inject
  private RabbitBinder binder;

  @PostConstruct
  public void initialize() {
    try {
      binder.configuration()
        .addHost("somehost.somedomain") // <1>
        .setUsername("myuser") // <2>
        .setPassword("mypassword"); // <3>
        .setSecure(true) // <4>
        .setConnectTimeout(10000) // <5>
        .setConnectRetryWaitTime(10000) // <6>
        .setRequestedConnectionHeartbeatTimeout(3) // <7>
        .withPrefetchCount(5); //8
      binder.initialize();
    } catch (IOException e) {
      LoggerFactory.getLogger(getClass()).error("Unable to initialize", e);
    }
  }
}
----
<1> Specifies a AMQP host name (there can be added more than one here)
<2> Specifies a connection user name
<3> Specifies a connection password
<4> Enables the transport layer security (TLS)
<5> Sets the connect timeout to 10 sec
<6> Set the time to wait between connection retries to 10 sec
<7> Set the heartbeat timeout to 3 sec (To detect connection problems)
<8> Set the prefetch count which configures how many messages are downloaded at once from broker

=== Alternative connection definition

Alternatively the connection can also be configured using a respective URI
string:

[source,java]
----
@Singleton
@Startup
public class BindingInitializer {
  @Inject
  private RabbitBinder binder;

  @PostConstruct
  public void initialize() {
    try {
      binder.configuration()
        .setUri("amqp://user:mysecret@somehost.somedomain/virtualhost"); // <1>
      binder.initialize();
    } catch (IOException e) {
      LoggerFactory.getLogger(getClass()).error("Unable to initialize", e);
    }
  }
}
----
<1> Specifies a AMQP connection URI

More information about the detailed URI can be found in the
https://www.rabbitmq.com/uri-spec.html[RabbitMQ URI specification].

=== Multiple server connections

In case you have to support two different servers, create a binder implementation
for each host and initialize them in one single binding initializer:

[source,java]
----
@Singleton
@Startup
public class BindingInitializer {
  @Inject
  private RabbitBinder binderOne;
  @Inject
  private RabbitBinder binderTwo;

  @PostConstruct
  public void initialize() {
    try {
      binderOne.configuration()
        .addHost("hostOne.somedomain")
        .setUsername("myuser")
        .setPassword("mypassword");
      binderTwo.configuration()
        .addHost("hostTwo.somedomain")
        .setUsername("myuser")
        .setPassword("mypassword");

      binderOne.initialize();
      binderTwo.initialize();
    } catch (IOException e) {
      LoggerFactory.getLogger(getClass()).error("Unable to initialize", e);
    }
  }
}
----

=== Usage in a container

Now the events can be used within your JavaEE container:

source,java]
----
public class EventDemoBean {
  @Inject
  private Event<EventOne> eventOnes;

  public void submitEvent(boolean enabled) {
    EventOne eventOne = new EventOne();
    eventOne.setEnabled(enabled);
    eventOnes.fire(eventOne);
  }

  public void receiveEvent(@Observes EventTwo eventTwo) {
    String data = eventTwo.getData();
    // do some work
  }
}
----

== Contribute

Contributions are always welcome. Use https://google.github.io/styleguide/javaguide.html[Google code style format] for your changes.

== License

This project is licensed under the https://github.com/{project-full-path}/blob/{github-branch}/LICENSE[MIT license]

= Provides a JavaEE Event <--> RabbitMQ bridge.
Patrick Reinhart <https://github.com/reinhapa[@reinhapa]>
:project-full-path: reinhapa/rabbitmq-cdi
:github-branch: master

image:https://img.shields.io/badge/license-MIT-blue.svg["MIT License", link="https://github.com/{project-full-path}/blob/{github-branch}/LICENSE"]
image:https://img.shields.io/badge/Java-8-blue.svg["Supported Versions", link="https://travis-ci.org/{project-full-path}"]
image:https://img.shields.io/badge/Java-9-blue.svg["Supported Versions", link="https://travis-ci.org/{project-full-path}"]
image:https://img.shields.io/badge/Java-10-blue.svg["Supported Versions", link="https://travis-ci.org/{project-full-path}"]
image:https://img.shields.io/badge/Java-11-blue.svg["Supported Versions", link="https://travis-ci.org/{project-full-path}"]
image:https://img.shields.io/badge/Java-12-blue.svg["Supported Versions", link="https://travis-ci.org/{project-full-path}"]
image:https://img.shields.io/github/release/{project-full-path}.svg["Release", link="https://github.com/{project-full-path}"]
image:https://img.shields.io/maven-central/v/net.reini/rabbitmq-cdi.svg?label=Maven%20Central["Maven Central", link="https://search.maven.org/search?q=g:%22net.reini%22%20AND%20a:%22rabbitmq-cdi%22"]
image:https://img.shields.io/travis/{project-full-path}/{github-branch}.svg["Build Status", link="https://travis-ci.org/{project-full-path}"]
image:https://img.shields.io/codecov/c/github/{project-full-path}/{github-branch}.svg["Code Coverage", link="https://codecov.io/github/{project-full-path}?branch={github-branch}"]
image:https://codecov.io/github/{project-full-path}/branch.svg?branch={github-branch}[codecov.io]

This project contains all needed classes to bind JavaEE enterprise events to a
RabbitMQ exchange for outgoing events. Inbound events can also be bound to the
respective queues and will be handed over to all JavaEE event observers.

The RabbitMQ message content is done via JSON serialization of a Java Bean
compatible PoJo object and vice versa.

== Usage example

First you need to define event objects using standard Java Bean syntax:

[source,java]
----
public class EventOne {
  private boolean enabled;

  public boolean isEnabled() {
    return enabled;
  }

  public void setEnabled(boolean enabled) {
    this.enabled = enabled;
  }
}

public class EventTwo {
  private String value;

  public String getValue() {
    return value;
  }

  public void setValue(String value) {
    this.value = value;
  }
}
----

As second step you have to define the bindings:

[source,java]
----
@Dependent
public class RabbitBinder extends EventBinder {
  @Override
  protected void bindEvents() {

    ExchangeDeclaration testExchangeOne = declarerFactory()
    .createExchangeDeclaration("test.exchange.one")
      .withExchangeType(BuiltinExchangeType.DIRECT)
      .withAutoDelete(false)
      .withDurable(false); // <1>

    QueueDeclaration testQueue = declarerFactory()
    .createQueueDeclaration("test.queue")
      .withAutoDelete(false)
      .withDurable(false)
      .withExclusiveAccess(false); // <2>

    bind(EventOne.class)
      .toExchange("test.exchange.one");
      .withDeclaration(testExchangeOne) // <3>
    bind(EventOne.class)
      .toExchange("test.exchange.two")
      .withRoutingKey("test.key")
      .withEncoder(new MyCustomEncoder()); // <4>

    bind(EventTwo.class)
      .toQueue("test.queue");
    bind(EventTwo.class)
      .toQueue("test.queue")
      .withDecoder(new MyCustomDecoder())
      .withDeclaration(testQueue)
      .autoAck(); // <5>
  }
}
----
<1> Create exchange declaration for exchange with name 'test.exchange.one' and type 'direct'
<2> Creates queue declaration for queue with name 'test.queue'
<3> Uses an empty routing key for exchange 'test.exchange.one' and adds exchange declaration for this publisher
<4> Specifies a custom event encoder
<5> Specifies a custom event decoder, enables auto acknowledge and adds queue declaration for this consumer

Note to declarations:

Created declarations are not automatically declared on broker side.
For each consumer/producer own channels exist because of that reason it is necessary to
add the declaration needed to a binding via .withDeclaration(..)
Only these declarations are applied for this consumer/producer

As last step you need to initialize the binder either in a singleton
startup bean or servlet after having also configured the connection settings:

[source,java]
----
@Singleton
@Startup
public class BindingInitializer {
  @Inject
  private RabbitBinder binder;

  @PostConstruct
  public void initialize() {
    try {
      binder.configuration()
        .addHost("somehost.somedomain") // <1>
        .setUsername("myuser") // <2>
        .setPassword("mypassword"); // <3>
        .setSecure(true) // <4>
        .setConnectTimeout(10000) // <5>
        .setConnectRetryWaitTime(10000) // <6>
        .setRequestedConnectionHeartbeatTimeout(3) // <7>
        .withPrefetchCount(5); //8
      binder.initialize();
    } catch (IOException e) {
      LoggerFactory.getLogger(getClass()).error("Unable to initialize", e);
    }
  }
}
----
<1> Specifies a AMQP host name (there can be added more than one here)
<2> Specifies a connection user name
<3> Specifies a connection password
<4> Enables the transport layer security (TLS)
<5> Sets the connect timeout to 10 sec
<6> Set the time to wait between connection retries to 10 sec
<7> Set the heartbeat timeout to 3 sec (To detect connection problems)
<8> Set the prefetch count which configures how many messages are downloaded at once from broker

=== Alternative connection definition

Alternatively the connection can also be configured using a respective URI
string:

[source,java]
----
@Singleton
@Startup
public class BindingInitializer {
  @Inject
  private RabbitBinder binder;

  @PostConstruct
  public void initialize() {
    try {
      binder.configuration()
        .setUri("amqp://user:mysecret@somehost.somedomain/virtualhost"); // <1>
      binder.initialize();
    } catch (IOException e) {
      LoggerFactory.getLogger(getClass()).error("Unable to initialize", e);
    }
  }
}
----
<1> Specifies a AMQP connection URI

More information about the detailed URI can be found in the
https://www.rabbitmq.com/uri-spec.html[RabbitMQ URI specification].

=== Multiple server connections

In case you have to support two different servers, create a binder implementation
for each host and initialize them in one single binding initializer:

[source,java]
----
@Singleton
@Startup
public class BindingInitializer {
  @Inject
  private RabbitBinder binderOne;
  @Inject
  private RabbitBinder binderTwo;

  @PostConstruct
  public void initialize() {
    try {
      binderOne.configuration()
        .addHost("hostOne.somedomain")
        .setUsername("myuser")
        .setPassword("mypassword");
      binderTwo.configuration()
        .addHost("hostTwo.somedomain")
        .setUsername("myuser")
        .setPassword("mypassword");

      binderOne.initialize();
      binderTwo.initialize();
    } catch (IOException e) {
      LoggerFactory.getLogger(getClass()).error("Unable to initialize", e);
    }
  }
}
----

=== Usage in a container

Now the events can be used within your JavaEE container:

source,java]
----
public class EventDemoBean {
  @Inject
  private Event<EventOne> eventOnes;

  public void submitEvent(boolean enabled) {
    EventOne eventOne = new EventOne();
    eventOne.setEnabled(enabled);
    eventOnes.fire(eventOne);
  }

  public void receiveEvent(@Observes EventTwo eventTwo) {
    String data = eventTwo.getData();
    // do some work
  }
}
----

== Contribute

Contributions are always welcome. Use https://google.github.io/styleguide/javaguide.html[Google code style format] for your changes.

== License

This project is licensed under the https://github.com/{project-full-path}/blob/{github-branch}/LICENSE[MIT license]


Improve README

Improve README

== Making an Index

`make_index` is a Ruby program for generating
an index for Asciidoc documents.  At the
moment it requires the `Asciidoctor-LaTeX` extension.

Mark terms like this if you want them to appear
in the document index:
----
   ((potrezebie))
----
Assuming that your document is `foo.adoc`, do
this to make a version with an index:
----
  $ ruby make_index.rb ../examples/foo.adoc
----
Execution of this command produces
two files, `foo-indexed.adoc`
and `foo-indexed.html`.  Here we assume
that you in the directory `make_index/lib`.

https://vschool.s3.amazonaws.com/manuscripts/462.html[Here]
is an example of an Asciidoc document compiled
with an index.  And
http://www.noteshare.io/lessons/index-example-1?remote=true&view_mode=source[here]
is a place to view the source text if you are
logged in to Noteshare.  If you wish,
you can sign up for
a free account at
http://www.noteshare.io[Noteshare.io].

.Larger Example
For testing purposes, the 5900-word file
`keynes_ch_2.adoc` is included.
It has a few terms marked marked for the
index.  To play with it, do this:
----
  $  ruby make_index.rb ../examples/keynes_ch_2.adoc
----
Then view the file `keynes_ch_2-indexed.html`
in your browser.

=== Installation

.Download from GitHub
----
  $ git clone https://github.com/jxxcarlson/asciidoctor-make-index
  $ https://github.com/asciidoctor/asciidoctor-latex
  $ cd asciidoctor-latex
  $ rake install
----

Run tests with `rspec spec/make_index_spec.rb`.

.Stopgap
Until I get things properly set up build and install
a gem, you should also
say

----
alias makeindex="ruby $HOME/dev/git/asciidoctor-make-index/lib/make_index.rb"
----

Then you can run `make-index foo.adoc` from anywhere.

.Help needed
When I run `rake install`, the gem is installed
as `make_index (0.1.0)` (verified)
by running `gem list`). but when I run `$ make_index foo.adoc`
I get the error 'make_index: command not found'

=== Notes

. The index feature of Asciidoctor-LaTeX experimental.
It is designed to be syntax-compatible with the
corresponding feature for Asciidoctor when
it is released.  At that point,
`make_index.rb` will be redundant.
. The index feature has beeb rolled into
http://www.noteshare.io[Noteshare.io].  The *Show Doc*
item in the *View* menu will compile the current notebook
with an index if the attribute `:make_index:` is set.
See http://www.noteshare.io/section/writing-tools#_index[this document]

== Making an Index

`make_index` is a Ruby program for generating
an index for Asciidoc documents.  At the
moment it requires the `Asciidoctor-LaTeX` extension.

Mark terms like this if you want them to appear
in the document index:
----
   ((potrezebie))
----
Assuming that your document is `foo.adoc`, do
this to make a version with an index:
----
  $ ruby make_index.rb ../examples/foo.adoc
----
Execution of this command produces
two files, `foo-indexed.adoc`
and `foo-indexed.html`.  Here we assume
that you in the directory `make_index/lib`.

.Larger Example
For testing purposes, the 5900-word file
`keynes_ch_2.adoc` is included.
It has a few terms marked marked for the
index.  To play with it, do this:
----
  $  ruby make_index.rb ../examples/keynes_ch_2.adoc
----
Then view the file `keynes_ch_2-indexed.html`
in your browser.

=== Installation

.Download from GitHub
----
  $ git clone https://github.com/jxxcarlson/asciidoctor-make-index
  $ https://github.com/asciidoctor/asciidoctor-latex
  $ cd asciidoctor-latex
  $ rake install
----

Run tests with `rspec spec/make_index_spec.rb`.

.Stopgap
Until I get things properly set up build and install
a gem, you should also
say

----
alias makeindex="ruby $HOME/dev/git/asciidoctor-make-index/lib/make_index.rb"
----

Then you can run `make-index foo.adoc` from anywhere.

.Help needed
When I run `rake install`, the gem is installed
as `make_index (0.1.0)` (verified)
by running `gem list`). but when I run `$ make_index foo.adoc`
I get the error 'make_index: command not found'

=== Notes

. The index feature of Asciidoctor-LaTeX experimental.
It is designed to be syntax-compatible with the
corresponding feature for Asciidoctor when
it is released.  At that point,
`make_index.rb` will be redundant.
. The index feature has beeb rolled into
http://www.noteshare.io[Noteshare.io].  The *Show Doc*
item in the *View* menu will compile the current notebook
with an index if the attribute `:make_index:` is set.
See http://www.noteshare.io/section/writing-tools#_index[this document]


Update readme for code of conduct.

Update readme for code of conduct.

https://github.com/spring-cloud/spring-cloud-build/issues/26

// Do not edit this file (e.g. go instead to docs/src/main/asciidoc)

image::https://travis-ci.org/spring-cloud/spring-cloud-cli.svg?branch=master[Build Status, link=https://travis-ci.org/spring-cloud/spring-cloud-cli]

Spring Boot CLI provides http://projects.spring.io/spring-boot[Spring Boot] command line features for
https://github.com/spring-cloud[Spring Cloud]. You can write Groovy scripts to run Spring Cloud component applications
(e.g. `@EnableEurekaServer`). You can also easily do things like encryption and decryption to support Spring Cloud
Config clients with secret configuration values.

== Installation

To install, make
sure you have
https://github.com/spring-projects/spring-boot[Spring Boot CLI]
(1.2.0 or better):

    $ spring version
    Spring CLI v1.2.3.RELEASE

E.g. for GVM users

```
$ gvm install springboot 1.3.0.M5
$ gvm use springboot 1.3.0.M5
```

and install the Spring Cloud plugin:

```
$ mvn install
$ spring install org.springframework.cloud:spring-cloud-cli:1.1.0.BUILD-SNAPSHOT
```

IMPORTANT: **Prerequisites:** to use the encryption and decryption features
you need the full-strength JCE installed in your JVM (it's not there by default).
You can download the "Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files"
from Oracle, and follow instructions for installation (essentially replace the 2 policy files
in the JRE lib/security directory with the ones that you downloaded).

== Building

:jdkversion: 1.7

=== Basic Compile and Test

To build the source you will need to install JDK {jdkversion}.

Spring Cloud uses Maven for most build-related activities, and you
should be able to get off the ground quite quickly by cloning the
project you are interested in and typing

----
$ ./mvnw install
----

NOTE: You can also install Maven (>=3.3.3) yourself and run the `mvn` command
in place of `./mvnw` in the examples below. If you do that you also
might need to add `-P spring` if your local Maven settings do not
contain repository declarations for spring pre-release artifacts.

NOTE: Be aware that you might need to increase the amount of memory
available to Maven by setting a `MAVEN_OPTS` environment variable with
a value like `-Xmx512m -XX:MaxPermSize=128m`. We try to cover this in
the `.mvn` configuration, so if you find you have to do it to make a
build succeed, please raise a ticket to get the settings added to
source control.

For hints on how to build the project look in `.travis.yml` if there
is one. There should be a "script" and maybe "install" command. Also
look at the "services" section to see if any services need to be
running locally (e.g. mongo or rabbit).  Ignore the git-related bits
that you might find in "before_install" since they're related to setting git
credentials and you already have those.

The projects that require middleware generally include a
`docker-compose.yml`, so consider using
http://compose.docker.io/[Docker Compose] to run the middeware servers
in Docker containers. See the README in the
https://github.com/spring-cloud-samples/scripts[scripts demo
repository] for specific instructions about the common cases of mongo,
rabbit and redis.

NOTE: If all else fails, build with the command from `.travis.yml` (usually
`./mvnw install`).

=== Documentation

The spring-cloud-build module has a "docs" profile, and if you switch
that on it will try to build asciidoc sources from
`src/main/asciidoc`. As part of that process it will look for a
`README.adoc` and process it by loading all the includes, but not
parsing or rendering it, just copying it to `${main.basedir}`
(defaults to `${basedir}`, i.e. the root of the project). If there are
any changes in the README it will then show up after a Maven build as
a modified file in the correct place. Just commit it and push the change.

=== Working with the code
If you don't have an IDE preference we would recommend that you use
http://www.springsource.com/developer/sts[Spring Tools Suite] or
http://eclipse.org[Eclipse] when working with the code. We use the
http://eclipse.org/m2e/[m2eclipe] eclipse plugin for maven support. Other IDEs and tools
should also work without issue.

==== Importing into eclipse with m2eclipse
We recommend the http://eclipse.org/m2e/[m2eclipe] eclipse plugin when working with
eclipse. If you don't already have m2eclipse installed it is available from the "eclipse
marketplace".

Unfortunately m2e does not yet support Maven 3.3, so once the projects
are imported into Eclipse you will also need to tell m2eclipse to use
the `.settings.xml` file for the projects.  If you do not do this you
may see many different errors related to the POMs in the
projects.  Open your Eclipse preferences, expand the Maven
preferences, and select User Settings.  In the User Settings field
click Browse and navigate to the Spring Cloud project you imported
selecting the `.settings.xml` file in that project.  Click Apply and
then OK to save the preference changes.

NOTE: Alternatively you can copy the repository settings from https://github.com/spring-cloud/spring-cloud-build/blob/master/.settings.xml[`.settings.xml`] into your own `~/.m2/settings.xml`.

==== Importing into eclipse without m2eclipse
If you prefer not to use m2eclipse you can generate eclipse project metadata using the
following command:

[indent=0]
----
	$ ./mvnw eclipse:eclipse
----

The generated eclipse projects can be imported by selecting `import existing projects`
from the `file` menu.

==== Adding Project Lombok Agent

Spring Cloud uses http://projectlombok.org/features/index.html[Project Lombok]
to generate getters and setters etc. Compiling from the command line this
shouldn't cause any problems, but in an IDE you need to add an agent
to the JVM. Full instructions can be found in the Lombok website. The
sign that you need to do this is a lot of compiler errors to do with
missing methods and fields, e.g.

[indent=0]
----
The method getInitialStatus() is undefined for the type EurekaInstanceConfigBean    EurekaDiscoveryClientConfiguration.java /spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka   line 120    Java Problem
The method getInitialStatus() is undefined for the type EurekaInstanceConfigBean    EurekaDiscoveryClientConfiguration.java /spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka   line 121    Java Problem
The method setNonSecurePort(int) is undefined for the type EurekaInstanceConfigBean EurekaDiscoveryClientConfiguration.java /spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka   line 112    Java Problem
The type EurekaInstanceConfigBean.IdentifyingDataCenterInfo must implement the inherited abstract method DataCenterInfo.getName()   EurekaInstanceConfigBean.java   /spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka   line 131    Java Problem
The method getId() is undefined for the type ProxyRouteLocator.ProxyRouteSpec   PreDecorationFilter.java    /spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/pre line 60 Java Problem
The method getLocation() is undefined for the type ProxyRouteLocator.ProxyRouteSpec PreDecorationFilter.java    /spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/pre line 55 Java Problem
----

==== Importing into Intellij
Spring Cloud projects use annotation processing, particularly Lombok, which requires configuration
or you will encounter compile problems. It also needs a specific version of maven and a profile
enabled. Intellij 14.1+ requires some configuration to ensure these are setup properly.

 1. Click Preferences, Plugins. *Ensure Lombok is installed*
 2. Click New, Project from Existing Sources, choose your spring-cloud-sleuth directory
 3. Choose Maven, and select Environment Settings. *Ensure you are using Maven 3.3.3*
 4. In the next screen, *Select the profile `spring`* click Next until Finish.
 5. Click Preferences, "Build, Execution, Deployment", Compiler, Annotation Processors. *Click Enable Annotation Processing*
 6. Click Build, Rebuild Project, and you are ready to go!

==== Importing into other IDEs
Maven is well supported by most Java IDEs. Refer to you vendor documentation.

== Contributing

Spring Cloud is released under the non-restrictive Apache 2.0 license,
and follows a very standard Github development process, using Github
tracker for issues and merging pull requests into master. If you want
to contribute even something trivial please do not hesitate, but
follow the guidelines below.

=== Sign the Contributor License Agreement
Before we accept a non-trivial patch or pull request we will need you to sign the
https://support.springsource.com/spring_committer_signup[contributor's agreement].
Signing the contributor's agreement does not grant anyone commit rights to the main
repository, but it does mean that we can accept your contributions, and you will get an
author credit if we do.  Active contributors might be asked to join the core team, and
given the ability to merge pull requests.

=== Code of Conduct
This project adheres to the Contributor Covenant https://github.com/spring-cloud/spring-cloud-build/blob/master/docs/src/main/asciidoc/code-of-conduct.adoc[code of
conduct]. By participating, you  are expected to uphold this code. Please report
unacceptable behavior to spring-code-of-conduct@pivotal.io.

=== Code Conventions and Housekeeping
None of these is essential for a pull request, but they will all help.  They can also be
added after the original pull request but before a merge.

* Use the Spring Framework code format conventions. If you use Eclipse
  you can import formatter settings using the
  `eclipse-code-formatter.xml` file from the
  https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/spring-cloud-dependencies-parent/eclipse-code-formatter.xml[Spring
  Cloud Build] project. If using IntelliJ, you can use the
  http://plugins.jetbrains.com/plugin/6546[Eclipse Code Formatter
  Plugin] to import the same file.
* Make sure all new `.java` files to have a simple Javadoc class comment with at least an
  `@author` tag identifying you, and preferably at least a paragraph on what the class is
  for.
* Add the ASF license header comment to all new `.java` files (copy from existing files
  in the project)
* Add yourself as an `@author` to the .java files that you modify substantially (more
  than cosmetic changes).
* Add some Javadocs and, if you change the namespace, some XSD doc elements.
* A few unit tests would help a lot as well -- someone has to do it.
* If no-one else is using your branch, please rebase it against the current master (or
  other target branch in the main project).
* When writing a commit message please follow http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html[these conventions],
  if you are fixing an existing issue please add `Fixes gh-XXXX` at the end of the commit
  message (where XXXX is the issue number).

// Do not edit this file (e.g. go instead to docs/src/main/asciidoc)

image::https://travis-ci.org/spring-cloud/spring-cloud-cli.svg?branch=master[Build Status, link=https://travis-ci.org/spring-cloud/spring-cloud-cli]

Spring Boot CLI provides http://projects.spring.io/spring-boot[Spring Boot] command line features for
https://github.com/spring-cloud[Spring Cloud]. You can write Groovy scripts to run Spring Cloud component applications
(e.g. `@EnableEurekaServer`). You can also easily do things like encryption and decryption to support Spring Cloud
Config clients with secret configuration values.

== Installation

To install, make
sure you have
https://github.com/spring-projects/spring-boot[Spring Boot CLI]
(1.2.0 or better):

    $ spring version
    Spring CLI v1.2.3.RELEASE

E.g. for GVM users

```
$ gvm install springboot 1.3.0.M5
$ gvm use springboot 1.3.0.M5
```

and install the Spring Cloud plugin:

```
$ mvn install
$ spring install org.springframework.cloud:spring-cloud-cli:1.1.0.BUILD-SNAPSHOT
```

IMPORTANT: **Prerequisites:** to use the encryption and decryption features
you need the full-strength JCE installed in your JVM (it's not there by default).
You can download the "Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files"
from Oracle, and follow instructions for installation (essentially replace the 2 policy files
in the JRE lib/security directory with the ones that you downloaded).

== Building

:jdkversion: 1.7

=== Basic Compile and Test

To build the source you will need to install JDK {jdkversion}.

Spring Cloud uses Maven for most build-related activities, and you
should be able to get off the ground quite quickly by cloning the
project you are interested in and typing

----
$ ./mvnw install
----

NOTE: You can also install Maven (>=3.3.3) yourself and run the `mvn` command
in place of `./mvnw` in the examples below. If you do that you also
might need to add `-P spring` if your local Maven settings do not
contain repository declarations for spring pre-release artifacts.

NOTE: Be aware that you might need to increase the amount of memory
available to Maven by setting a `MAVEN_OPTS` environment variable with
a value like `-Xmx512m -XX:MaxPermSize=128m`. We try to cover this in
the `.mvn` configuration, so if you find you have to do it to make a
build succeed, please raise a ticket to get the settings added to
source control.

For hints on how to build the project look in `.travis.yml` if there
is one. There should be a "script" and maybe "install" command. Also
look at the "services" section to see if any services need to be
running locally (e.g. mongo or rabbit).  Ignore the git-related bits
that you might find in "before_install" since they're related to setting git
credentials and you already have those.

The projects that require middleware generally include a
`docker-compose.yml`, so consider using
http://compose.docker.io/[Docker Compose] to run the middeware servers
in Docker containers. See the README in the
https://github.com/spring-cloud-samples/scripts[scripts demo
repository] for specific instructions about the common cases of mongo,
rabbit and redis.

NOTE: If all else fails, build with the command from `.travis.yml` (usually
`./mvnw install`).

=== Documentation

The spring-cloud-build module has a "docs" profile, and if you switch
that on it will try to build asciidoc sources from
`src/main/asciidoc`. As part of that process it will look for a
`README.adoc` and process it by loading all the includes, but not
parsing or rendering it, just copying it to `${main.basedir}`
(defaults to `${basedir}`, i.e. the root of the project). If there are
any changes in the README it will then show up after a Maven build as
a modified file in the correct place. Just commit it and push the change.

=== Working with the code
If you don't have an IDE preference we would recommend that you use
http://www.springsource.com/developer/sts[Spring Tools Suite] or
http://eclipse.org[Eclipse] when working with the code. We use the
http://eclipse.org/m2e/[m2eclipe] eclipse plugin for maven support. Other IDEs and tools
should also work without issue.

==== Importing into eclipse with m2eclipse
We recommend the http://eclipse.org/m2e/[m2eclipe] eclipse plugin when working with
eclipse. If you don't already have m2eclipse installed it is available from the "eclipse
marketplace".

Unfortunately m2e does not yet support Maven 3.3, so once the projects
are imported into Eclipse you will also need to tell m2eclipse to use
the `.settings.xml` file for the projects.  If you do not do this you
may see many different errors related to the POMs in the
projects.  Open your Eclipse preferences, expand the Maven
preferences, and select User Settings.  In the User Settings field
click Browse and navigate to the Spring Cloud project you imported
selecting the `.settings.xml` file in that project.  Click Apply and
then OK to save the preference changes.

NOTE: Alternatively you can copy the repository settings from https://github.com/spring-cloud/spring-cloud-build/blob/master/.settings.xml[`.settings.xml`] into your own `~/.m2/settings.xml`.

==== Importing into eclipse without m2eclipse
If you prefer not to use m2eclipse you can generate eclipse project metadata using the
following command:

[indent=0]
----
	$ ./mvnw eclipse:eclipse
----

The generated eclipse projects can be imported by selecting `import existing projects`
from the `file` menu.

==== Adding Project Lombok Agent

Spring Cloud uses http://projectlombok.org/features/index.html[Project Lombok]
to generate getters and setters etc. Compiling from the command line this
shouldn't cause any problems, but in an IDE you need to add an agent
to the JVM. Full instructions can be found in the Lombok website. The
sign that you need to do this is a lot of compiler errors to do with
missing methods and fields, e.g.

[indent=0]
----
The method getInitialStatus() is undefined for the type EurekaInstanceConfigBean    EurekaDiscoveryClientConfiguration.java /spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka   line 120    Java Problem
The method getInitialStatus() is undefined for the type EurekaInstanceConfigBean    EurekaDiscoveryClientConfiguration.java /spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka   line 121    Java Problem
The method setNonSecurePort(int) is undefined for the type EurekaInstanceConfigBean EurekaDiscoveryClientConfiguration.java /spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka   line 112    Java Problem
The type EurekaInstanceConfigBean.IdentifyingDataCenterInfo must implement the inherited abstract method DataCenterInfo.getName()   EurekaInstanceConfigBean.java   /spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka   line 131    Java Problem
The method getId() is undefined for the type ProxyRouteLocator.ProxyRouteSpec   PreDecorationFilter.java    /spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/pre line 60 Java Problem
The method getLocation() is undefined for the type ProxyRouteLocator.ProxyRouteSpec PreDecorationFilter.java    /spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/pre line 55 Java Problem
----

==== Importing into Intellij
Spring Cloud projects use annotation processing, particularly Lombok, which requires configuration
or you will encounter compile problems. It also needs a specific version of maven and a profile
enabled. Intellij 14.1+ requires some configuration to ensure these are setup properly.

 1. Click Preferences, Plugins. *Ensure Lombok is installed*
 2. Click New, Project from Existing Sources, choose your spring-cloud-sleuth directory
 3. Choose Maven, and select Environment Settings. *Ensure you are using Maven 3.3.3*
 4. In the next screen, *Select the profile `spring`* click Next until Finish.
 5. Click Preferences, "Build, Execution, Deployment", Compiler, Annotation Processors. *Click Enable Annotation Processing*
 6. Click Build, Rebuild Project, and you are ready to go!

==== Importing into other IDEs
Maven is well supported by most Java IDEs. Refer to you vendor documentation.

== Contributing

Spring Cloud is released under the non-restrictive Apache 2.0 license,
and follows a very standard Github development process, using Github
tracker for issues and merging pull requests into master. If you want
to contribute even something trivial please do not hesitate, but
follow the guidelines below.

=== Sign the Contributor License Agreement
Before we accept a non-trivial patch or pull request we will need you to sign the
https://support.springsource.com/spring_committer_signup[contributor's agreement].
Signing the contributor's agreement does not grant anyone commit rights to the main
repository, but it does mean that we can accept your contributions, and you will get an
author credit if we do.  Active contributors might be asked to join the core team, and
given the ability to merge pull requests.

=== Code Conventions and Housekeeping
None of these is essential for a pull request, but they will all help.  They can also be
added after the original pull request but before a merge.

* Use the Spring Framework code format conventions. If you use Eclipse
  you can import formatter settings using the
  `eclipse-code-formatter.xml` file from the
  https://github.com/spring-cloud/spring-cloud-build/blob/master/spring-cloud-build/eclipse-code-formatter.xml[Spring
  Cloud Build] project. If using IntelliJ, you can use the
  http://plugins.jetbrains.com/plugin/6546[Eclipse Code Formatter
  Plugin] to import the same file.
* Make sure all new `.java` files to have a simple Javadoc class comment with at least an
  `@author` tag identifying you, and preferably at least a paragraph on what the class is
  for.
* Add the ASF license header comment to all new `.java` files (copy from existing files
  in the project)
* Add yourself as an `@author` to the .java files that you modify substantially (more
  than cosmetic changes).
* Add some Javadocs and, if you change the namespace, some XSD doc elements.
* A few unit tests would help a lot as well -- someone has to do it.
* If no-one else is using your branch, please rebase it against the current master (or
  other target branch in the main project).
* When writing a commit message please follow http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html[these conventions],
  if you are fixing an existing issue please add `Fixes gh-XXXX` at the end of the commit
  message (where XXXX is the issue number).


badge links corrected

badge links corrected

https://maven-badges.herokuapp.com/maven-central/com.github.oboehm/gdv-xport[image:https://maven-badges.herokuapp.com/maven-central/com.github.oboehm/gdv-xport/badge.svg[Maven Metadata]]
https://travis-ci.org/oboehm/gdv.xport[image:https://api.travis-ci.org/oboehm/gdv.xport.svg?branch=develop/3.x[BuildStatus]]
https://coveralls.io/github/oboehm/gdv.xport[image:https://coveralls.io/repos/github/oboehm/gdv.xport/badge.svg?branch=develop%2F3.x[Coverage Status]]
http://www.apache.org/licenses/LICENSE-2.0.html[image:https://img.shields.io/badge/license-Apache%202.0-blue.svg[Apache License 2.0]]

= Was ist gdv.xport?

gdv.xport ist als Java-Bibliothek gestartet, die den Umgang mit dem GDV-Format erleichtert.
Das "x" in port steht fur "im"- und "ex"-port. Die Bibliothek ist Open Source und steht unter der Apache License.

Mit Version 3.0 gibt es neben dieser Bibliothek auch REST-Services fuer Dateien im GDV-Format.
Die einzelnen Module sind:

* *gdv-xport-lib*: gdv.xport als Java-Bibliothek
* *gdv-xport-service*: gdv.xport-Services (Spring-Boot-Anwendung)

== Kompatibilitaet von v2 zu v3

Waehrend Version 2 auf der 2013er-Version der XML-Datei von "gdv-online":http://www.gdv-online.de/vuvm/index.htm basiert,
wurde Version 3 auf die aktuelle Version von 2015 aktualisiert.
Diese Aenderungen sind aber abwaertskompatibel.
Allerdings wurde mit der Aktualisierung auch die Bezeichner-Klasse ueberarbeitet:

* die String-Konstanten "NAME_xxx", die als _@Deprecated_ waren, wurden entfernt,
* die Bezeichner-Konstanten wurden geprueft, Schreibfehler entfernt und doppelte Eintraege entfernt,
* verwaiste Konstanten, die in der XML-Datei nicht vorhanden sind, wurden entfernt.

Dadurch kann es sein, dass manche Konstanten irrtuemlich geloescht wurden.
Sollte dies der Fall sein, ein "Issue":https://github.com/oboehm/gdv.xport/issues/ erstellen.
Man kann natuerlich auch die Konstanten in seiner Anwendung selber definieren.

== Aehnliche Projekte

Fuer Ruby gibt es "OpenGDV":https://github.com/vendis/opengdv/, einer Open-Source-Bibliothek, die unter der MIT-License steht.
Allerdings wurde diese Bibliothek schon seit laengerer Zeit nicht mehr aktualisiert.

== GIT Branching-Modell

Entwickelt wird nach "A successful Git branching model":http://nvie.com/posts/a-successful-git-branching-model/ von Vincent Driessen.
Die Weiterentwicklung der aktuellen Version findet auf dem develop-Branch statt (derzeit: "develop/3.x":https://github.com/oboehm/gdv.xport/tree/develop/3.x), waehrend das letzte Release im Release-Zweig (derzeit: "release/3.x":https://github.com/oboehm/gdv.xport/tree/release/3.x) zu finden ist.

== Weitere Infos

Im "Wiki":https://github.com/oboehm/gdv.xport/wiki ist alles Wichtige zu gdv.xport zusammengefasst.
Weitere Infos wie z.B. die "JavaDocs":http://www.aosd.de/gdv.xport/apidocs/index.html finden Sie auch auf der "Maven Projekt-Seite":http://www.aosd.de/gdv.xport/ .

* CI-Build: https://travis-ci.org/oboehm/gdv.xport
* Wiki: https://github.com/oboehm/gdv.xport/wiki
* Projekt-Seite: http://www.aosd.de/gdv.xport/

image:https://maven-badges.herokuapp.com/maven-central/com.github.oboehm/gdv-xport/badge.svg[Maven metadata URI]
image:https://api.travis-ci.org/oboehm/gdv.xport.svg?branch=develop/3.x[BuildStatus]
image:https://coveralls.io/repos/github/oboehm/gdv.xport/badge.svg?branch=develop%2F3.x[Coverage Status]
image:https://img.shields.io/badge/license-Apache%202.0-blue.svg[Apache License 2.0]

= Was ist gdv.xport?

gdv.xport ist als Java-Bibliothek gestartet, die den Umgang mit dem GDV-Format erleichtert.
Das "x" in port steht fur "im"- und "ex"-port. Die Bibliothek ist Open Source und steht unter der Apache License.

Mit Version 3.0 gibt es neben dieser Bibliothek auch REST-Services fuer Dateien im GDV-Format.
Die einzelnen Module sind:

* *gdv-xport-lib*: gdv.xport als Java-Bibliothek
* *gdv-xport-service*: gdv.xport-Services (Spring-Boot-Anwendung)

== Kompatibilitaet von v2 zu v3

Waehrend Version 2 auf der 2013er-Version der XML-Datei von "gdv-online":http://www.gdv-online.de/vuvm/index.htm basiert,
wurde Version 3 auf die aktuelle Version von 2015 aktualisiert.
Diese Aenderungen sind aber abwaertskompatibel.
Allerdings wurde mit der Aktualisierung auch die Bezeichner-Klasse ueberarbeitet:

* die String-Konstanten "NAME_xxx", die als _@Deprecated_ waren, wurden entfernt,
* die Bezeichner-Konstanten wurden geprueft, Schreibfehler entfernt und doppelte Eintraege entfernt,
* verwaiste Konstanten, die in der XML-Datei nicht vorhanden sind, wurden entfernt.

Dadurch kann es sein, dass manche Konstanten irrtuemlich geloescht wurden.
Sollte dies der Fall sein, ein "Issue":https://github.com/oboehm/gdv.xport/issues/ erstellen.
Man kann natuerlich auch die Konstanten in seiner Anwendung selber definieren.

== Aehnliche Projekte

Fuer Ruby gibt es "OpenGDV":https://github.com/vendis/opengdv/, einer Open-Source-Bibliothek, die unter der MIT-License steht.
Allerdings wurde diese Bibliothek schon seit laengerer Zeit nicht mehr aktualisiert.

== GIT Branching-Modell

Entwickelt wird nach "A successful Git branching model":http://nvie.com/posts/a-successful-git-branching-model/ von Vincent Driessen.
Die Weiterentwicklung der aktuellen Version findet auf dem develop-Branch statt (derzeit: "develop/3.x":https://github.com/oboehm/gdv.xport/tree/develop/3.x), waehrend das letzte Release im Release-Zweig (derzeit: "release/3.x":https://github.com/oboehm/gdv.xport/tree/release/3.x) zu finden ist.

== Weitere Infos

Im "Wiki":https://github.com/oboehm/gdv.xport/wiki ist alles Wichtige zu gdv.xport zusammengefasst.
Weitere Infos wie z.B. die "JavaDocs":http://www.aosd.de/gdv.xport/apidocs/index.html finden Sie auch auf der "Maven Projekt-Seite":http://www.aosd.de/gdv.xport/ .

* CI-Build: https://travis-ci.org/oboehm/gdv.xport
* Wiki: https://github.com/oboehm/gdv.xport/wiki
* Projekt-Seite: http://www.aosd.de/gdv.xport/


update README

update README

Signed-off-by: Thomas Sjögren <9ff28d1cb1d19283ed3327b40df6c7d62d8bc343@users.noreply.github.com>

image::logo/horizontal.png[Ubuntu Hardening]

= Hardening Ubuntu. Systemd edition.
:icons: font

A quick way to make a Ubuntu server a bit more secure.

Tested on `Ubuntu 20.04 Focal Fossa` and `Ubuntu 20.10 Groovy Gorilla (development branch)`.

Systemd required.

If you're just interested in the security focused systemd configuration, it's
available as a link:systemd.adoc[separate document].

If you're interested in testing your host settings, you'll find the
link:README.adoc#tests[instructions here].

NOTE: This is a constant work in progress. Make sure you understand what it
does. `Read the code`.

== Howto
Start the installation of the server. +
Pick language, keyboard layout, timezone and so on as you usually would.

=== Partition the system
[source,shell]
----
/
/boot (rw)
/home (rw,nosuid,nodev)
swap
/var
/var/log (rw,nosuid,nodev,noexec)
/var/log/audit (rw,nosuid,nodev,noexec)
/var/tmp (rw,noexec,nodev,nosuid)
----

Note that `/tmp` will be added automatically by the script.

=== Login, set a Grub2 password, configure and run ubuntu.sh
Do not add any packages. +
Log in. +
Select a Grub2 password with `grub-mkpasswd-pbkdf2`. +
Download the script: `git clone https://github.com/konstruktoid/hardening.git`. +
Change the configuration options in the `ubuntu.cfg` file. +
Run the script: `sudo bash ubuntu.sh`. +
Reboot.

If possible, use the newly installed and configured system as a reference,
or golden, image. Use that image as a baseline installation media and ensure
that any future installation comply with benchmarks and policies using a
configuration management tool, e.g https://www.ansible.com/[Ansible] or
https://puppet.com/[Puppet].

If you're using Ansible, a playbook with most of the functions in this script is
available in my Ansible repository https://github.com/konstruktoid/ansible-role-hardening[konstruktoid/ansible-role-hardening].

== Configuration options
[source,shell]
----
FW_ADMIN='127.0.0.1' // <1>
SSH_GRPS='sudo' // <2>
SSH_PORT='22' // <3>
SYSCTL_CONF='./misc/sysctl.conf' // <4>
AUDITD_MODE='1' // <5>
AUDITD_RULES='./misc/audit-base.rules ./misc/audit-aggressive.rules ./misc/audit-docker.rules' // <6>
LOGROTATE_CONF='./misc/logrotate.conf' // <7>
NTPSERVERPOOL='0.ubuntu.pool.ntp.org 1.ubuntu.pool.ntp.org 2.ubuntu.pool.ntp.org 3.ubuntu.pool.ntp.org pool.ntp.org' // <8>
TIMEDATECTL='' // <9>
VERBOSE='N' // <10>
AUTOFILL='N' // <11>
CHANGEME='' // <12>

# Configuration files
ADDUSER='/etc/adduser.conf'
AUDITDCONF='/etc/audit/auditd.conf'
AUDITRULES='/etc/audit/rules.d/hardening.rules'
COMMONPASSWD='/etc/pam.d/common-password'
COMMONACCOUNT='/etc/pam.d/common-account'
COMMONAUTH='/etc/pam.d/common-auth'
COREDUMPCONF='/etc/systemd/coredump.conf'
DEFAULTGRUB='/etc/default/grub.d'
DISABLEFS='/etc/modprobe.d/disablefs.conf'
DISABLEMOD='/etc/modprobe.d/disablemod.conf'
DISABLENET='/etc/modprobe.d/disablenet.conf'
JOURNALDCONF='/etc/systemd/journald.conf'
LIMITSCONF='/etc/security/limits.conf'
LOGINDCONF='/etc/systemd/logind.conf'
LOGINDEFS='/etc/login.defs'
LOGROTATE='/etc/logrotate.conf'
PAMLOGIN='/etc/pam.d/login'
RESOLVEDCONF='/etc/systemd/resolved.conf'
RKHUNTERCONF='/etc/default/rkhunter'
RSYSLOGCONF='/etc/rsyslog.conf'
SECURITYACCESS='/etc/security/access.conf'
SSHFILE='/etc/ssh/ssh_config'
SSHDFILE='/etc/ssh/sshd_config'
SYSCTL='/etc/sysctl.conf'
SYSTEMCONF='/etc/systemd/system.conf'
TIMESYNCD='/etc/systemd/timesyncd.conf'
UFWDEFAULT='/etc/default/ufw'
USERADD='/etc/default/useradd'
USERCONF='/etc/systemd/user.conf'
----
<1> The IP addresses that will be able to connect with SSH, separated by spaces.
<2> Which group the users have to be member of in order to acess via SSH, separated by spaces.
<3> Configure SSH port.
<4> Stricter sysctl settings.
<5> Auditd failure mode. 0=silent 1=printk 2=panic.
<6> Auditd rules.
<7> Logrotate settings.
<8> NTP server pool.
<9> Add a specific time zone or use the system default by leaving it empty.
<10> If you want all the details or not.
<11> Let the script guess the `FW_ADMIN` and `SSH_GRPS` settings.
<12> Add something just to verify that you actually glanced the code.

== Functions

=== Function list

==== 01_pre
Setup script, sets APT flags and permission checks.

==== 02_firewall
Enable `ufw`, use `/etc/sysctl.conf`, and allow port 22 from `$FW_ADMIN`.

==== 03_disablenet
Disable `dccp` `sctp` `rds` `tipc` protocols.

==== 04_disablemnt
Disable `cramfs` `freevxfs` `jffs2` `hfs` `hfsplus` `squashfs` `udf` `vfat` file
systems.

==== 05_systemdconf
Disable coredumps and crash shells, set `DefaultLimitNOFILE` and
`DefaultLimitNPROC` to 1024.

==== 06_journalctl
Compress logs, forward to syslog and make log storage persistent. Ensure rsyslog
writes logs with stricter permissions.

==== 07_timesyncd
Add four NTP-servers with a latency < 50ms from `$NTPSERVERPOOL`.

==== 08_fstab
Configure `/tmp/` and `/var/tmp/`. Remove floppy drivers from `/etc/fstab`
and add `hidepid=2` to `/proc`.

==== 09_prelink
Undo prelinking, and remove `prelink` package.

==== 10_aptget
Configure `dpkg` and `apt-get`. `apt-get` update and upgrade.

==== 11_hosts
`/etc/hosts.allow` and `/etc/hosts.deny` restrictions.

==== 12_logindefs
Modify `/etc/login.defs`, e.g. `UMASK`, password age limits and
`SHA_CRYPT_MAX_ROUNDS`.

==== 13_sysctl
Update `$SYSCTL` with `$SYSCTL_CONF`.

==== 14_limits
Set hard and soft limits.

==== 15_adduser
Configure `useradd` and `adduser` to set `/bin/false` as default shell,
home directory permissions to `0750` and lock users 30 days after password
expires.

==== 16_rootaccess
Limit `/etc/securetty` to `console`, and `root` from 127.0.0.1 in
`/etc/security/access.conf`.

==== 17_packages
Installs `acct` `aide-common` `apparmor-profiles` `apparmor-utils` `auditd`
`audispd-plugins` `debsums` `gnupg2` `haveged` `libpam-apparmor`
`libpam-cracklib` `libpam-tmpdir` `needrestart` `openssh-server` `postfix`
`rkhunter` `sysstat` `systemd-coredump` `tcpd` `update-notifier-common`
`vlock`.

Removes `apport*` `autofs` `avahi*` `beep` `git` `pastebinit`
`popularity-contest` `rsh*` `rsync` `talk*` `telnet*` `tftp*` `whoopsie`
`xinetd` `yp-tools` `ypbind`.

==== 18_sshdconfig
Configure the `OpenSSH`-daemon.

==== 19_password
Configure `pam_cracklib.so` and `pam_tally2.so`.

==== 20_cron
Allow `root` to use `cron`. Mask `atd`.

==== 21_ctraltdel
Disable Ctrl-alt-delete.

==== 22_auditd
Configure `auditd`, use `$AUDITD_RULES` and set failure mode `$AUDITD_MODE`.

==== 23_disablemod
Disable `bluetooth` `bnep` `btusb` `cpia2` `firewire-core` `floppy` `n_hdlc`
`net-pf-31` `pcspkr` `soundcore` `thunderbolt` `usb-midi` `usb-storage`
`uvcvideo` `v4l2_common` kernel modules.

Note that disabling the `usb-storage` will disable any usage of USB storage
devices, if such devices are needed `USBGuard` should be configured accordingly.

==== 24_aide
Configure `aide`.

==== 25_rhosts
Remove `hosts.equiv` and `.rhosts`.

==== 26_users
Remove `games` `gnats` `irc` `list` `news` `sync` `uucp` users.

==== 27_suid
Remove `suid` bits from the executables listed in
link:misc/suid.list[this document].

==== 28_umask
Set `bash` and `/etc/profile` umask.

==== 29_apparmor
Enforce present `apparmor` profiles.

==== 30_path
Set `root` path to `/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin`,
and user path to `/usr/local/bin:/usr/bin:/bin`.

==== 31_logindconf
Configure `systemd/logind.conf` and use `KillUserProcesses`.

==== 32_resolvedconf
Configure `systemd/resolved.conf`.

==== 33_rkhunter
Configure `rkhunter`.

==== 34_issue
Update `/etc/issue` `/etc/issue.net` `/etc/motd`.

==== 35_apport
Disable `apport`, `ubuntu-report` and `popularity-contest`.

==== 36_lockroot
Lock the `root` user account.

==== 37_coredump
Disable coredumps with `systemd/coredump.conf`.

==== 38_postfix
Disable the `VRFY` command, configure `smtpd_banner`, `smtpd_client_restrictions`
and `inet_interfaces`.

==== 39_motdnews
Disable `motd-news`.

==== 40_usbguard
Install and configure `usbguard`.

==== 41_compilers
Restrict compiler access.

==== 42_kernel
Set `lockdown=confidentiality` if `/sys/kernel/security/lockdown` is present.

==== 43_sudo
Configure `sudo` with `use_pty`, `logfile`, `!visiblepw`, `!pwfeedback`,
`passwd_timeout` and `timestamp_timeout`.

Restrict `su` to the `sudo` group.

==== 98_systemddelta
If verbose, show `systemd-delta`.

==== 99_post
Ensure `secureboot-db` is installed, update grub and ensure strict permissions
on boot files.

==== 99_reboot
Print if a reboot is required.

=== Function execution order
[source,shell]
----
f_pre
f_kernel
f_firewall
f_disablenet
f_disablefs
f_disablemod
f_systemdconf
f_resolvedconf
f_logindconf
f_journalctl
f_timesyncd
f_fstab
f_prelink
f_aptget_configure
f_aptget
f_hosts
f_issue
f_sudo
f_logindefs
f_sysctl
f_limitsconf
f_adduser
f_rootaccess
f_package_install
f_coredump
f_usbguard
f_postfix
f_apport
f_motdnews
f_rkhunter
f_sshconfig
f_sshdconfig
f_password
f_cron
f_ctrlaltdel
f_auditd
f_aide
f_rhosts
f_users
f_lockroot
f_package_remove
f_suid
f_restrictcompilers
f_umask
f_path
f_aa_enforce
f_aide_post
f_aide_timer
f_aptget_noexec
f_aptget_clean
f_systemddelta
f_post
f_checkreboot
----

== Tests
There are approximately 700 https://github.com/sstephenson/bats[Bats tests]
for most of the above settings available in the link:tests/[tests directory].

[source,shell]
----
sudo apt-get -y install bats
git clone https://github.com/konstruktoid/hardening.git
cd hardening/tests/
sudo bats .
----

=== Test automation using Vagrant
Running `bash ./runTests.sh` will use https://www.vagrantup.com/[Vagrant] to run
all above tests and https://github.com/CISOfy/Lynis[Lynis] on all supported Ubuntu
versions. The script will generate a file named `TESTRESULTS.adoc`.

=== Testing a host
Running `bash ./runHostTests.sh`, located in the link:tests/[tests directory],
will generate a `TESTRESULTS-<HOSTNAME>.adoc` report.

=== OpenSCAP testing
To run a https://github.com/ComplianceAsCode/content[OpenSCAP] test on a
Ubuntu host, where `v0.1.49` should be replaced with the latest available
version:

[source,shell]
----
sudo apt-get -y install libopenscap8 unzip
wget https://github.com/ComplianceAsCode/content/releases/download/v0.1.49/scap-security-guide-0.1.49-oval-510.zip
unzip scap-security-guide-0.1.49-oval-510.zip
cd scap-security-guide-0.1.49-oval-5.10
oscap info --fetch-remote-resources ./ssg-ubuntu1804-ds.xml
sudo oscap xccdf eval --fetch-remote-resources \
  --profile xccdf_org.ssgproject.content_profile_anssi_np_nt28_high \
  --report ../bionic_stig-report.html ./ssg-ubuntu1804-ds.xml
----

== Recommended reading
https://public.cyber.mil/stigs/downloads/?_dl_facet_stigs=operating-systems%2Cunix-linux[Canonical Ubuntu 18.04 LTS STIG - Ver 1, Rel 1] +
https://www.cisecurity.org/benchmark/distribution_independent_linux/[CIS Distribution Independent Linux Benchmark] +
https://www.cisecurity.org/benchmark/ubuntu_linux/[CIS Ubuntu Linux Benchmark] +
https://www.ncsc.gov.uk/collection/end-user-device-security/platform-specific-guidance/ubuntu-18-04-lts[EUD Security Guidance: Ubuntu 18.04 LTS]
https://public.cyber.mil/stigs/downloads/?_dl_facet_stigs=operating-systems%2Cunix-linux[Red Hat Enterprise Linux 7 - Ver 2, Rel 3 STIG] +
https://wiki.ubuntu.com/Security/Features +
https://help.ubuntu.com/community/StricterDefaults +

== Contributing
Do you want to contribute? That's great! Contributions are always welcome,
no matter how large or small. If you found something odd, feel free to
https://github.com/konstruktoid/hardening/issues/[submit a new issue],
improve the code by https://github.com/konstruktoid/hardening/pulls[creating a pull request],
or by https://github.com/sponsors/konstruktoid[sponsoring this project].

Logo by https://github.com/reallinfo[reallinfo].

image::logo/horizontal.png[Ubuntu Hardening]

= Hardening Ubuntu. Systemd edition.
:icons: font

A quick way to make a Ubuntu server a bit more secure.

Tested on `Ubuntu 20.04 Focal Fossa` and `Ubuntu 20.10 Groovy Gorilla (development branch)`.

Systemd required.

If you're just interested in the security focused systemd configuration, it's
available as a link:systemd.adoc[separate document].

If you're interested in testing your host settings, you'll find the
link:README.adoc#tests[instructions here].

NOTE: This is a constant work in progress. Make sure you understand what it
does. `Read the code`.

== Howto
Start the installation of the server. +
Pick language, keyboard layout, timezone and so on as you usually would.

=== Partition the system
[source,shell]
----
/
/boot (rw)
/home (rw,nosuid,nodev)
swap
/var
/var/log (rw,nosuid,nodev,noexec)
/var/log/audit (rw,nosuid,nodev,noexec)
/var/tmp (rw,noexec,nodev,nosuid)
----

Note that `/tmp` will be added automatically by the script.

=== Login, set a Grub2 password, configure and run ubuntu.sh
Do not add any packages. +
Log in. +
Select a Grub2 password with `grub-mkpasswd-pbkdf2`. +
Download the script: `git clone https://github.com/konstruktoid/hardening.git`. +
Change the configuration options in the `ubuntu.cfg` file. +
Run the script: `sudo bash ubuntu.sh`. +
Reboot.

If possible, use the newly installed and configured system as a reference,
or golden, image. Use that image as a baseline installation media and ensure
that any future installation comply with benchmarks and policies using a
configuration management tool, e.g https://www.ansible.com/[Ansible] or
https://puppet.com/[Puppet].

If you're using Ansible, a playbook with most of the functions in this script is
available in my Ansible repository https://github.com/konstruktoid/ansible-role-hardening[konstruktoid/ansible-role-hardening].

== Configuration options
[source,shell]
----
FW_ADMIN='127.0.0.1' // <1>
SSH_GRPS='sudo' // <2>
SSH_PORT='22' // <3>
SYSCTL_CONF='./misc/sysctl.conf' // <4>
AUDITD_MODE='1' // <5>
AUDITD_RULES='./misc/audit-base.rules ./misc/audit-aggressive.rules ./misc/audit-docker.rules' // <6>
LOGROTATE_CONF='./misc/logrotate.conf' // <7>
NTPSERVERPOOL='0.ubuntu.pool.ntp.org 1.ubuntu.pool.ntp.org 2.ubuntu.pool.ntp.org 3.ubuntu.pool.ntp.org pool.ntp.org' // <8>
TIMEDATECTL='' // <9>
VERBOSE='N' // <10>
AUTOFILL='N' // <11>
CHANGEME='' // <12>

# Configuration files
ADDUSER='/etc/adduser.conf'
AUDITDCONF='/etc/audit/auditd.conf'
AUDITRULES='/etc/audit/rules.d/hardening.rules'
COMMONPASSWD='/etc/pam.d/common-password'
COMMONACCOUNT='/etc/pam.d/common-account'
COMMONAUTH='/etc/pam.d/common-auth'
COREDUMPCONF='/etc/systemd/coredump.conf'
DEFAULTGRUB='/etc/default/grub.d'
DISABLEFS='/etc/modprobe.d/disablefs.conf'
DISABLEMOD='/etc/modprobe.d/disablemod.conf'
DISABLENET='/etc/modprobe.d/disablenet.conf'
JOURNALDCONF='/etc/systemd/journald.conf'
LIMITSCONF='/etc/security/limits.conf'
LOGINDCONF='/etc/systemd/logind.conf'
LOGINDEFS='/etc/login.defs'
LOGROTATE='/etc/logrotate.conf'
PAMLOGIN='/etc/pam.d/login'
RESOLVEDCONF='/etc/systemd/resolved.conf'
RKHUNTERCONF='/etc/default/rkhunter'
RSYSLOGCONF='/etc/rsyslog.conf'
SECURITYACCESS='/etc/security/access.conf'
SSHFILE='/etc/ssh/ssh_config'
SSHDFILE='/etc/ssh/sshd_config'
SYSCTL='/etc/sysctl.conf'
SYSTEMCONF='/etc/systemd/system.conf'
TIMESYNCD='/etc/systemd/timesyncd.conf'
UFWDEFAULT='/etc/default/ufw'
USERADD='/etc/default/useradd'
USERCONF='/etc/systemd/user.conf'
----
<1> The IP addresses that will be able to connect with SSH, separated by spaces.
<2> Which group the users have to be member of in order to acess via SSH, separated by spaces.
<3> Configure SSH port.
<4> Stricter sysctl settings.
<5> Auditd failure mode. 0=silent 1=printk 2=panic.
<6> Auditd rules.
<7> Logrotate settings.
<8> NTP server pool.
<9> Add a specific time zone or use the system default by leaving it empty.
<10> If you want all the details or not.
<11> Let the script guess the `FW_ADMIN` and `SSH_GRPS` settings.
<12> Add something just to verify that you actually glanced the code.

== Functions

=== Function list

==== 01_pre
Setup script, sets APT flags and permission checks.

==== 02_firewall
Enable `ufw`, use `/etc/sysctl.conf`, and allow port 22 from `$FW_ADMIN`.

==== 03_disablenet
Disable `dccp` `sctp` `rds` `tipc` protocols.

==== 04_disablemnt
Disable `cramfs` `freevxfs` `jffs2` `hfs` `hfsplus` `squashfs` `udf` `vfat` file
systems.

==== 05_systemdconf
Disable coredumps and crash shells, set `DefaultLimitNOFILE` and
`DefaultLimitNPROC` to 1024.

==== 06_journalctl
Compress logs, forward to syslog and make log storage persistent. Ensure rsyslog
writes logs with stricter permissions.

==== 07_timesyncd
Add four NTP-servers with a latency < 50ms from `$NTPSERVERPOOL`.

==== 08_fstab
Configure `/tmp/` and `/var/tmp/`. Remove floppy drivers from `/etc/fstab`
and add `hidepid=2` to `/proc`.

==== 09_prelink
Undo prelinking, and remove `prelink` package.

==== 10_aptget
Configure `dpkg` and `apt-get`. `apt-get` update and upgrade.

==== 11_hosts
`/etc/hosts.allow` and `/etc/hosts.deny` restrictions.

==== 12_logindefs
Modify `/etc/login.defs`, e.g. `UMASK`, password age limits and
`SHA_CRYPT_MAX_ROUNDS`.

==== 13_sysctl
Update `$SYSCTL` with `$SYSCTL_CONF`.

==== 14_limits
Set hard and soft limits.

==== 15_adduser
Set `/bin/false` as default shell when adding users.

==== 16_rootaccess
Limit `/etc/securetty` to `console`, and `root` from 127.0.0.1 in
`/etc/security/access.conf`.

==== 17_packages
Installs `acct` `aide-common` `apparmor-profiles` `apparmor-utils` `auditd`
`audispd-plugins` `debsums` `gnupg2` `haveged` `libpam-apparmor`
`libpam-cracklib` `libpam-tmpdir` `needrestart` `openssh-server` `postfix`
`rkhunter` `sysstat` `systemd-coredump` `tcpd` `update-notifier-common`
`vlock`.

Removes `apport*` `autofs` `avahi*` `beep` `git` `pastebinit`
`popularity-contest` `rsh*` `rsync` `talk*` `telnet*` `tftp*` `whoopsie`
`xinetd` `yp-tools` `ypbind`.

==== 18_sshdconfig
Configure the `OpenSSH`-daemon.

==== 19_password
Configure `pam_cracklib.so` and `pam_tally2.so`.

==== 20_cron
Allow `root` to use `cron`. Mask `atd`.

==== 21_ctraltdel
Disable Ctrl-alt-delete.

==== 22_auditd
Configure `auditd`, use `$AUDITD_RULES` and set failure mode `$AUDITD_MODE`.

==== 23_disablemod
Disable `bluetooth` `bnep` `btusb` `cpia2` `firewire-core` `floppy` `n_hdlc`
`net-pf-31` `pcspkr` `soundcore` `thunderbolt` `usb-midi` `usb-storage`
`uvcvideo` `v4l2_common` kernel modules.

Note that disabling the `usb-storage` will disable any usage of USB storage
devices, if such devices are needed `USBGuard` should be configured accordingly.

==== 24_aide
Configure `aide`.

==== 25_rhosts
Remove `hosts.equiv` and `.rhosts`.

==== 26_users
Remove `games` `gnats` `irc` `list` `news` `sync` `uucp` users.

==== 27_suid
Remove `suid` bits from the executables listed in
link:misc/suid.list[this document].

==== 28_umask
Set `bash` and `/etc/profile` umask.

==== 29_apparmor
Enforce present `apparmor` profiles.

==== 30_path
Set `root` path to `/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin`,
and user path to `/usr/local/bin:/usr/bin:/bin`.

==== 31_logindconf
Configure `systemd/logind.conf` and use `KillUserProcesses`.

==== 32_resolvedconf
Configure `systemd/resolved.conf`.

==== 33_rkhunter
Configure `rkhunter`.

==== 34_issue
Update `/etc/issue` `/etc/issue.net` `/etc/motd`.

==== 35_apport
Disable `apport`, `ubuntu-report` and `popularity-contest`.

==== 36_lockroot
Lock the `root` user account.

==== 37_coredump
Disable coredumps with `systemd/coredump.conf`.

==== 38_postfix
Disable the `VRFY` command, configure `smtpd_banner`, `smtpd_client_restrictions`
and `inet_interfaces`.

==== 39_motdnews
Disable `motd-news`.

==== 40_usbguard
Install and configure `usbguard`.

==== 41_compilers
Restrict compiler access.

==== 42_kernel
Set `lockdown=confidentiality` if `/sys/kernel/security/lockdown` is present.

==== 43_sudo
Configure `sudo` `use_pty`, `logfile`, `!visiblepw`, `!pwfeedback` and
`passwd_timeout`.

==== 98_systemddelta
If verbose, show `systemd-delta`.

==== 99_post
Ensure `secureboot-db` is installed, update grub and ensure strict permissions
on boot files.

==== 99_reboot
Print if a reboot is required.

=== Function execution order
[source,shell]
----
f_pre
f_kernel
f_firewall
f_disablenet
f_disablefs
f_disablemod
f_systemdconf
f_resolvedconf
f_logindconf
f_journalctl
f_timesyncd
f_fstab
f_prelink
f_aptget_configure
f_aptget
f_hosts
f_issue
f_sudo
f_logindefs
f_sysctl
f_limitsconf
f_adduser
f_rootaccess
f_package_install
f_coredump
f_usbguard
f_postfix
f_apport
f_motdnews
f_rkhunter
f_sshconfig
f_sshdconfig
f_password
f_cron
f_ctrlaltdel
f_auditd
f_aide
f_rhosts
f_users
f_lockroot
f_package_remove
f_suid
f_restrictcompilers
f_umask
f_path
f_aa_enforce
f_aide_post
f_aide_timer
f_aptget_noexec
f_aptget_clean
f_systemddelta
f_post
f_checkreboot
----

== Tests
There are approximately 700 https://github.com/sstephenson/bats[Bats tests]
for most of the above settings available in the link:tests/[tests directory].

[source,shell]
----
sudo apt-get -y install bats
git clone https://github.com/konstruktoid/hardening.git
cd hardening/tests/
sudo bats .
----

=== Test automation using Vagrant
Running `bash ./runTests.sh` will use https://www.vagrantup.com/[Vagrant] to run
all above tests and https://github.com/CISOfy/Lynis[Lynis] on all supported Ubuntu
versions. The script will generate a file named `TESTRESULTS.adoc`.

=== Testing a host
Running `bash ./runHostTests.sh`, located in the link:tests/[tests directory],
will generate a `TESTRESULTS-<HOSTNAME>.adoc` report.

=== OpenSCAP testing
To run a https://github.com/ComplianceAsCode/content[OpenSCAP] test on a
Ubuntu host, where `v0.1.49` should be replaced with the latest available
version:

[source,shell]
----
sudo apt-get -y install libopenscap8 unzip
wget https://github.com/ComplianceAsCode/content/releases/download/v0.1.49/scap-security-guide-0.1.49-oval-510.zip
unzip scap-security-guide-0.1.49-oval-510.zip
cd scap-security-guide-0.1.49-oval-5.10
oscap info --fetch-remote-resources ./ssg-ubuntu1804-ds.xml
sudo oscap xccdf eval --fetch-remote-resources \
  --profile xccdf_org.ssgproject.content_profile_anssi_np_nt28_high \
  --report ../bionic_stig-report.html ./ssg-ubuntu1804-ds.xml
----

== Recommended reading
https://public.cyber.mil/stigs/downloads/?_dl_facet_stigs=operating-systems%2Cunix-linux[Canonical Ubuntu 18.04 LTS STIG - Ver 1, Rel 1] +
https://www.cisecurity.org/benchmark/distribution_independent_linux/[CIS Distribution Independent Linux Benchmark] +
https://www.cisecurity.org/benchmark/ubuntu_linux/[CIS Ubuntu Linux Benchmark] +
https://www.ncsc.gov.uk/collection/end-user-device-security/platform-specific-guidance/ubuntu-18-04-lts[EUD Security Guidance: Ubuntu 18.04 LTS]
https://public.cyber.mil/stigs/downloads/?_dl_facet_stigs=operating-systems%2Cunix-linux[Red Hat Enterprise Linux 7 - Ver 2, Rel 3 STIG] +
https://wiki.ubuntu.com/Security/Features +
https://help.ubuntu.com/community/StricterDefaults +

== Contributing
Do you want to contribute? That's great! Contributions are always welcome,
no matter how large or small. If you found something odd, feel free to
https://github.com/konstruktoid/hardening/issues/[submit a new issue],
improve the code by https://github.com/konstruktoid/hardening/pulls[creating a pull request],
or by https://github.com/sponsors/konstruktoid[sponsoring this project].

Logo by https://github.com/reallinfo[reallinfo].


fixes #19

fixes #19

# Photon Event Store

Photon is an event store with cold+hot event streaming.

In microservices, each service is supposed to take responsibility for a single functional capability: a computational process. In this context, these processes will follow the same pattern: gathering sequences of inputs and generating sequences of outputs though transformation functions, also called projections. Usually such functions are deeply coupled with both 1) the implementation of the service and 2) the data consumed to generate a current state and outputs. As a consequence, designs and implementations of the concepts of storage, sequence handling and data transformation have to be repeated over and over again across different services.

Photon is an attempt at avoiding such redundancy by abstracting and encapsulating both the storage and the transformation of data as service methods. It is designed as a black box with an internal database with a projection engine, both generic enough to store free-form data and allow for a wide range of expressivity for data transformation, in real time. In this way, business rules can be implemented and deployed in Photon instances via projections, effectively decoupling business logic and data storage and processing.

## Quickstart

Download the link:https://github.com/muoncore/muon-starter[Muon Starter] repository and run through the instructions and
pre-requisites from there. The latest released version of photon will be started using Docker Compose,
along with a contained RabbitMQ instance for communication and other support microservices.

Install the link:https://github.com/muoncore/muon-cli[Muon CLI] and set up with the URL `amqp://muon:microservices@localhost`

You can then see photon running

```bash
> muon d

┌──────────────────────────────┬──────────────────────────────┬──────────────────────────────┐
│ SERVICE NAME                 │ TAGS                         │ CONTENT/TYPE                 │
├──────────────────────────────┼──────────────────────────────┼──────────────────────────────┤
│ molecule                     │                              │ application/json             │
├──────────────────────────────┼──────────────────────────────┼──────────────────────────────┤
│ photon                       │ photon,eventstore            │ application/json             │
└──────────────────────────────┴──────────────────────────────┴──────────────────────────────┘
```

You can emit an event using the CLI

```bash
> muon event '{ "event-type": "SomethingHappened", "schema": "1","stream-name": "something","payload": {"message": "Hi there!"}}'
```

This will persist the event in the given stream. It can be replayed at any point later on

You can replay the persisted events using the CLI

```bash

> muon replay something

```

All the events stored will then be replayed.

Check the latest http://muoncore.io/submodules/photon/doc/index.html[photon documentation] for more information.

Check the http://muoncore.io/guide/index.html to see patterns for developing with events using Photon

## Developing Photon

### Prerequisites

You will need [Leiningen][] 2.0.0 or above installed.

https://github.com/technomancy/leiningen[leiningen]

### Running

You can run photon directly from the source:

```
lein do cljsbuild once, run
```

Or you can build an uberjar:

```
lein do cljsbuild once, uberjar
java -jar photon-*-standalone.jar
```

### Admin Console

Once running, point your browser to: `http[s]://HOST:PORT/index.html`. HOST and PORT can be configured as seen below.

.Migration of UI
****
This console will be migrated to the Molecule project once the Molecule plugin system is stable.
****

### Startup options

```
Usage: java -jar photon-x.x.x-standalone.jar [-h] [-option value] ... [-option value]
Options:
-microservice.name    : Service ID, especially important for Muon (default = photon)
-rest.host            : The IP or hostname of the web server for frontend and API. Change it for external access (default = localhost)
-rest.port            : The port for the UI frontend and the REST API
-rest.keystore        : If set, the web server will be started in SSL mode using the certificates identified by this path
-rest.keypass         : The password required to open the keystore set in rest.keystore. Not required in not-SSL mode
-admin.user           : The default username for logging in and requesting API tokens (default = admin)
-admin.pass           : The default password for logging in and requesting API tokens (default = p4010n)
-admin.secret         : A secret string that will be used to encode authentication tokens (default is random on launch)
-projections.port     : Port to stream projection updates to (default = 8375)
-events.port          : Port to stream incoming events to (default = 8376)
-muon.url             : AMQP endpoint for Muon-based transport and discovery (default = amqp://localhost)
-parallel.projections : Number of cores assigned for parallel stream processing (default = number of cores on your machine)
-projections.path     : Local folder with projections, in EDN format, to pre-load on start (default = /tmp/photon)
-db.backend           : DB backend plugin to use (default=h2). Depending on the build of photon, this can be one of:
                        h2, cassandra, redis, file, mongo, riak, dummy.
-h2.path              : If using H2, the file prefix for the database file, including path (default = /tmp/photon.h2)
-cassandra.ip         : If using Cassandra, the host of the cluster
-file.path            : If using files as backend, the absolute path to the file
-mongodb.host         : If using MongoDB, the host of the cluster
-riak.default_bucket  : If using Riak, the name of the bucket
-riak.node.X          : If using Riak, the nodes that form the cluster (riak.node.1, riak.node.2, etc.)
```

### Setting up a file for static configuration

Photon can be configured either directly from the command line or from a file, and parameters can be combined from different sources. The order of priority in which the configuration is build is the following:

1. Command-line arguments
2. photon.properties in the working directory
3. resources/photon.properties
4. resources/config.properties

Example of property file:

```
# Microservice identifier (default = photon):
microservice.name=photon
# AMQP endpoint (default = amqp://localhost):
muon.url=amqp://username:password@localhost
# Number of cores assigned for parallel stream processing
# (default = number of cores on your machine):
parallel.projections=8
# Local folder with projections, in EDN format, to pre-load on start
# (default = /tmp/photon):
file.path=/path/to/edn-files/
# DB backend plugin to use, several options currently available:
db.backend={file,mongodb,riak,cassandra}
# Depending on the backend, you'll need to set up the DB plugin:
cassandra.ip=127.0.0.1
file.path=/path/to/file.json
mongodb.host=localhost
riak.default_bucket=photon-eventstore-v1
riak.node.1=riak1.yourdomain.com
riak.node.2=riak2.yourdomain.com
riak.node.3=riak3.yourdomain.com
```

### Muon schemas

The endpoints and expected schemas to interact with `photon` can be found [here](doc/schemas.md).

### Testing

Tests are run by executing

```
lein midje
```

To run the test suite from the REPL:

```bash
lein repl
=> (use 'midje.sweet)
=> (autotest)
```

Alternatively, create a test photon client to interact with photon:

```bash
lein new muon-clojure photon-test-client
```

### Profiling

In order to achieve the best performance and thoughput, photon has been intensively tested and profiled with the [YourKit](https://www.yourkit.com) profiler, with a license kindly provided by their creators as part of their support to the open source community.

image:https://www.yourkit.com/images/yklogo.png[YourKit logo]

YourKit supports open source projects with its full-featured Java Profiler.
YourKit, LLC is the creator of YourKit Java Profiler
and YourKit .NET Profiler,
innovative and intelligent tools for profiling Java and .NET applications.

# Photon Event Store

Photon is an event store with cold+hot event streaming.

In microservices, each service is supposed to take responsibility for a single functional capability: a computational process. In this context, these processes will follow the same pattern: gathering sequences of inputs and generating sequences of outputs though transformation functions, also called projections. Usually such functions are deeply coupled with both 1) the implementation of the service and 2) the data consumed to generate a current state and outputs. As a consequence, designs and implementations of the concepts of storage, sequence handling and data transformation have to be repeated over and over again across different services.

Photon is an attempt at avoiding such redundancy by abstracting and encapsulating both the storage and the transformation of data as service methods. It is designed as a black box with an internal database with a projection engine, both generic enough to store free-form data and allow for a wide range of expressivity for data transformation, in real time. In this way, business rules can be implemented and deployed in Photon instances via projections, effectively decoupling business logic and data storage and processing.

## Quickstart

Download the link:https://github.com/muoncore/muon-starter[Muon Starter] repository and run through the instructions and
pre-requisites from there. The latest released version of photon will be started using Docker Compose,
along with a contained RabbitMQ instance for communication and other support microservices.

Install the link:https://github.com/muoncore/muon-cli[Muon CLI] and set up with the URL `amqp://muon:microservices@localhost`

You can then see photon running

```bash
> muon d

┌──────────────────────────────┬──────────────────────────────┬──────────────────────────────┐
│ SERVICE NAME                 │ TAGS                         │ CONTENT/TYPE                 │
├──────────────────────────────┼──────────────────────────────┼──────────────────────────────┤
│ molecule                     │                              │ application/json             │
├──────────────────────────────┼──────────────────────────────┼──────────────────────────────┤
│ photon                       │ photon,eventstore            │ application/json             │
└──────────────────────────────┴──────────────────────────────┴──────────────────────────────┘
```

You can emit an event using the CLI

```bash
> muon event '{ "event-type": "SomethingHappened", "schema": "1","stream-name": "something","payload": {"message": "Hi there!"}}'
```

This will persist the event in the given stream. It can be replayed at any point later on

You can replay the persisted events using the CLI

```bash

> muon replay something

```

All the events stored will then be replayed.

Check the latest http://muoncore.io/submodules/photon/docs/index.html[photon documentation] for more information.

Check the http://muoncore.io/guide/index.html[Muon Guide "12 Days of Muon"] to see patterns for developing with events using Photon

## Developing Photon

### Prerequisites

You will need [Leiningen][] 2.0.0 or above installed.

https://github.com/technomancy/leiningen[leiningen]

### Running

You can run photon directly from the source:

```
lein do cljsbuild once, run
```

Or you can build an uberjar:

```
lein do cljsbuild once, uberjar
java -jar photon-*-standalone.jar
```

### Admin Console

Once running, point your browser to: `http[s]://HOST:PORT/index.html`. HOST and PORT can be configured as seen below.

.Migration of UI
****
This console will be migrated to the Molecule project once the Molecule plugin system is stable.
****

### Startup options

```
Usage: java -jar photon-x.x.x-standalone.jar [-h] [-option value] ... [-option value]
Options:
-microservice.name    : Service ID, especially important for Muon (default = photon)
-rest.host            : The IP or hostname of the web server for frontend and API. Change it for external access (default = localhost)
-rest.port            : The port for the UI frontend and the REST API
-rest.keystore        : If set, the web server will be started in SSL mode using the certificates identified by this path
-rest.keypass         : The password required to open the keystore set in rest.keystore. Not required in not-SSL mode
-admin.user           : The default username for logging in and requesting API tokens (default = admin)
-admin.pass           : The default password for logging in and requesting API tokens (default = p4010n)
-admin.secret         : A secret string that will be used to encode authentication tokens (default is random on launch)
-projections.port     : Port to stream projection updates to (default = 8375)
-events.port          : Port to stream incoming events to (default = 8376)
-muon.url             : AMQP endpoint for Muon-based transport and discovery (default = amqp://localhost)
-parallel.projections : Number of cores assigned for parallel stream processing (default = number of cores on your machine)
-projections.path     : Local folder with projections, in EDN format, to pre-load on start (default = /tmp/photon)
-db.backend           : DB backend plugin to use (default=h2). Depending on the build of photon, this can be one of:
                        h2, cassandra, redis, file, mongo, riak, dummy.
-h2.path              : If using H2, the file prefix for the database file, including path (default = /tmp/photon.h2)
-cassandra.ip         : If using Cassandra, the host of the cluster
-file.path            : If using files as backend, the absolute path to the file
-mongodb.host         : If using MongoDB, the host of the cluster
-riak.default_bucket  : If using Riak, the name of the bucket
-riak.node.X          : If using Riak, the nodes that form the cluster (riak.node.1, riak.node.2, etc.)
```

### Setting up a file for static configuration

Photon can be configured either directly from the command line or from a file, and parameters can be combined from different sources. The order of priority in which the configuration is build is the following:

1. Command-line arguments
2. photon.properties in the working directory
3. resources/photon.properties
4. resources/config.properties

Example of property file:

```
# Microservice identifier (default = photon):
microservice.name=photon
# AMQP endpoint (default = amqp://localhost):
muon.url=amqp://username:password@localhost
# Number of cores assigned for parallel stream processing
# (default = number of cores on your machine):
parallel.projections=8
# Local folder with projections, in EDN format, to pre-load on start
# (default = /tmp/photon):
file.path=/path/to/edn-files/
# DB backend plugin to use, several options currently available:
db.backend={file,mongodb,riak,cassandra}
# Depending on the backend, you'll need to set up the DB plugin:
cassandra.ip=127.0.0.1
file.path=/path/to/file.json
mongodb.host=localhost
riak.default_bucket=photon-eventstore-v1
riak.node.1=riak1.yourdomain.com
riak.node.2=riak2.yourdomain.com
riak.node.3=riak3.yourdomain.com
```

### Muon schemas

The endpoints and expected schemas to interact with `photon` can be found [here](doc/schemas.md).

### Testing

Tests are run by executing

```
lein midje
```

To run the test suite from the REPL:

```bash
lein repl
=> (use 'midje.sweet)
=> (autotest)
```

Alternatively, create a test photon client to interact with photon:

```bash
lein new muon-clojure photon-test-client
```

### Profiling

In order to achieve the best performance and thoughput, photon has been intensively tested and profiled with the [YourKit](https://www.yourkit.com) profiler, with a license kindly provided by their creators as part of their support to the open source community.

image:https://www.yourkit.com/images/yklogo.png[YourKit logo]

YourKit supports open source projects with its full-featured Java Profiler.
YourKit, LLC is the creator of YourKit Java Profiler
and YourKit .NET Profiler,
innovative and intelligent tools for profiling Java and .NET applications.