Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature Request: Add toml file specifically for captive core #3442

Closed
tamirms opened this issue Mar 4, 2021 · 6 comments · Fixed by #3629
Closed

Feature Request: Add toml file specifically for captive core #3442

tamirms opened this issue Mar 4, 2021 · 6 comments · Fixed by #3629

Comments

@tamirms
Copy link
Contributor

tamirms commented Mar 4, 2021

What problem does your feature solve?

The configuration space for the captive core append path file is not fully documented. Operators don't know what is possible to configure in captive core so they try to copy parts of the stellar-core.cfg file from their stand-alone stellar core instances into the captive core configuration. However, it's not clear which fields can and can't be set, which forces operators to go through a trial and error process of trying different combinations of fields until they get their setup to work.

What would you like to see?

We should create a restricted toml file just for captive core which is a subset of stellar-core.cfg.

The restricted toml file should be documented with an example cfg file just like the one in the stellar core repo: https://github.com/stellar/stellar-core/blob/master/docs/stellar-core_example.cfg

We should strive to make sure that configuration is not duplicated between horizon command line flags and the captive core toml file.

@ire-and-curses
Copy link
Contributor

Let's discuss this. What are the pros and cons?

@Shaptic
Copy link
Contributor

Shaptic commented Mar 4, 2021

One of the cons we should definitely keep in mind is that by pulling in a TOML parser, we're now exposing a potential attack vector to malicious user input. I'm not sure we should worry about that much, given that if you can control the config file, you can control everything else about Horizon anyway, but it's still worth keeping in mind, especially given our recent discussions about security.

@tamirms
Copy link
Contributor Author

tamirms commented Mar 12, 2021

If we have a separate toml file for captive core we should consider allowing LOG_FILE_PATH to be configured. If LOG_FILE_PATH is set we will store captive core logs in that location and remove captive core output from the horizon log stream. If LOG_FILE_PATH is not set then we can default to the current behavior of including captive core logs in the horizon log stream.

One point of duplication we need to figure out is how to deal with the configuration of history archive urls. History archive urls are part of horizon configuration and stellar core configuration. Ideally we should not have to configure both. But the difficulty is that stellar core's configuration is more expressive than horizon. It allows for specifying how core should obtain the history archives (e.g. curl -sf %s/{0} -o {1} or aws s3 cp s3://history.stellar.org/{0} {1})

@Shaptic
Copy link
Contributor

Shaptic commented Mar 12, 2021

After the discussion with ops, I think this has progressed into a far bigger, arguably meta-issue.

Should we push to make Horizon configured by toml files entirely, just like Stellar Core? Then, it will simply contain a subsection related to Captive Core configurations (while the rest will be a tomlification replacing Horizon's existing CLI / env params entirely). While this subsection may "look" just like Core's, its validity will be controlled by us entirely. This encourages our don't worry about Core's existence abstraction intended by Horizon 2.0 and Captive Core.

This transition will subsequently encompass all of the config-related issues, like #3437, #3438, #3441, and undoubtedly others that will pop up.

(Technically this breaking change would require releasing Horizon 3.0 which is a little odd, but that's the nature of semver.)

@bartekn
Copy link
Contributor

bartekn commented Mar 16, 2021

(Technically this breaking change would require releasing Horizon 3.0 which is a little odd, but that's the nature of semver.)

This can be done in a non-breaking way (however requires some extra work): if config file param is set (--config-file maybe?) all of the other flags are ignored, if it's not set we read the flags using existing code.

Pros, cons and random thoughts:

  • P: The same format (toml) is used for Stellar-Core and Horizon which are often used together.
  • P: toml allows setting more complicated structures than command line flag. One example is history archives which is currently a comma separated string in Horizon.
  • P: Avoids duplication in some cases like network passphrase (but sometimes impossible - read on).
  • C: One time requirement for rewriting Horizon configuration to use a new format.
  • C: This won't solve the usability issue: while it will be easier for users to create a new config (by copy&paste) they won't be able to use existing file without modifications.
  • Some changes in Stellar-Core are required if we want to avoid duplication completely. For example: Horizon asks for plain URLs when configuring history archives, Stellar-Core requires users to set a command (like curl) that will be used to download the files. Because of this users will have to set two archive values anyway. I opened Consider processing buckets in memory in captive mode stellar-core#2942 hoping that we can parse the files in memory however it seems that Stellar-Core needs these files for bucket hash calculations after each ledger. I'm going to ask it's possible to add code that downloads the buckets instead of relying on external tool.

@Shaptic
Copy link
Contributor

Shaptic commented Mar 17, 2021

This can be done in a non-breaking way [...]

Good point. We can even consolidate the code to essentially make an in-memory TOML file from env/cli parameters, making it easier to drop the latter entirely in a future version and ensure we only have a single parsing / validation path. e.g.

User --> [CLI] ----+
User --> [ENV] ----|
                   |
User --> [TOML] <--+
            |
            v
         Horizon

This won't solve the usability issue: [...]

With proper parsing, we'll be able to advise users much better, e.g. these lines are ignored, this line is wrong, here's a Horizon-compatible toml, etc. which is still a big win over the current "Captive Core isn't running because of a bad config" state.

For example: Horizon asks for plain URLs when configuring history archives, Stellar-Core requires users to set a command [...]

Can we make it such that we essentially add an extra parameter to the Stellar-Core command in which we populate the URL, or would that be even more confusing? e.g. instead of the following:

HISTORY="curl -sf http://history.stellar.org/prd/core-testnet/core_testnet_001/{0} -o {1}"

We have

HISTORY_ARCHIVE_URL="http://history.stellar.org/prd/core-testnet/core_testnet_001"
HISTORY="curl -sf {0}/{1} -o {2}"

Unfortunately there are some assumptions built-in to the form of the HISTORY_ARCHIVE_URL in that case, so maybe this isn't a great approach. The cleanest approach is probably just keeping both around.

@bartekn bartekn added this to the Horizon 2.2.0 milestone Mar 31, 2021
@tamirms tamirms self-assigned this Apr 1, 2021
tamirms added a commit that referenced this issue May 5, 2021
…ging (#3558)

This PR fixes #3486 and lays the groundwork for implementing #3442 .

This PR changes how we interpret captive core append file (configured via --captive-core-config-append-path). Previously, we automatically generated the stellar core toml file for the captive core subprocess in ingest/ledgerbackend/stellar_core_runner.go by presetting some defaults and then concatenating the generated configuration with the user supplied append file.

This strategy did not work out so well because sometimes horizon operators included configuration in the append file which was already configured in the presets generated by ingest/ledgerbackend/stellar_core_runner.go. An example of this type of error can be found in #3486 .

Now, in this PR, instead of generating the stellar core toml file via simple string concatenation we actually parse the user supplied append file and try to do more robust merging between the user supplied configuration and the captive core preset defaults. The merging code is implemented in ingest/ledgerbackend/toml.go .

The merging strategy is unfortunately complicated by the fact that captive core configuration can come from 3 places:

User supplied append file
horizon command line flag (e.g. --captive-core-peer-port, --captive-core-http-port, etc)
default values which we preset (e.g. DISABLE_XDR_FSYNC)
In theory the user supplied append file should only contain the quorum set but in practice we have never validated the append file to ensure that it configures a quorum set and nothing else. We could simplify the merging logic in this PR by choosing to validate the append file in this way. I decided not to take that approach because I think that it would be a breaking change for many horizon operators (including SDF) who have configuration in the append file which is not related to quorum sets. If you disagree with this design decision please let me know.

The merging algorithm generally works as follows:

If there is a configuration field which is set both in source (1) and source (2) we check that both sources provide equivalent values, otherwise we return an error.

The exception to this rule is the history archive configuration. We take the history archive configuration from source (1) and completely disregard what is provided in source (2) unless there is no history archive configuration in source (1). The reason for this is that it's difficult to compare the history archive values from source (1) and source (2).

If a configuration field is defined in source (1) but not source (2), we will use the field which is explicitly defined. The same logic applies if the field is defined in source (2) but not source (1).

Finally, if there is no configuration defined in either source (1) or source (2), we use the value from source (3).

In the next PR, my plan is to fully implement #3442 by introducing a new horizon command line flag --captive-core-config-file which deprecates --captive-core-config-append-path. The difference between --captive-core-config-file and --captive-core-config-append-path is that the validation is stricter.

--captive-core-config-file will not allow any unknown fields to be present in the toml file.

Furthermore, if --captive-core-config-file is provided then you will not be allowed to use any horizon command line flags to configure captive core. In other words, --captive-core-config-file deprecates source (2).

Along with defining --captive-core-config-file, the next PR will also add documentation for the captive core configuration file in an captive-core_example.cfg file (similar to how stellar core does it https://github.com/stellar/stellar-core/blob/master/docs/stellar-core_example.cfg ). The example file will document the full range of configuration options available to captive core instances.

Unfortunately there will be some slight differences between the stellar core example cfg and the captive core example cfg because captive core has different defaults compared to stellar core. For example, captive core sets DISABLE_XDR_FSYNC to true by default whereas stellar core sets DISABLE_XDR_FSYNC to false by default. We should think carefully about each of the cases where captive core diverges from stellar core.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants