logo_kerberos.gif

Difference between revisions of "Projects/Profile Includes"

From K5Wiki
Jump to: navigation, search
(New page: {{project-early}} ==Background== In a [http://mailman.mit.edu/pipermail/krbdev/2010-July/009170.html July 2010 mailing list discussion] about dynamic module discovery, consensus was reac...)
 
 
(12 intermediate revisions by the same user not shown)
Line 1: Line 1:
{{project-early}}
+
{{project-rel|1.9}}
   
 
==Background==
 
==Background==
   
In a [http://mailman.mit.edu/pipermail/krbdev/2010-July/009170.html July 2010 mailing list discussion] about dynamic module discovery, consensus was reached that the profile library should gain support for include-file functionality with pattern matching. This project is to add that support.
+
In a [http://mailman.mit.edu/pipermail/krbdev/2010-July/009171.html July 2010 mailing list discussion] about dynamic module discovery, consensus was reached that the profile library should gain support for include-file functionality with the ability to include a variable set of files within a directory. This project is to add that support.
   
 
==Interface Design==
 
==Interface Design==
   
A profile file may contain a line "include PATTERN". PATTERN is expanded for shell wildcards and all matching files, if any, are read, with lines from those files parsed as if they belonged to the original krb5.conf file. If no files match, the line has no effect.
+
A profile file may contain a line "include FILENAME". FILENAME is read, and relations from the file are added to the original profile. If FILENAME does not exist or cannot be read, profile parsing fails.
  +
  +
A profile file may include a line "includedir DIRNAME". If DIRNAME does not exist or is unreadable, profile parsing fails. Files within DIRNAME, whose names consist only of alphanumeric characters, dashes, and underscores, are read and their relations added to the original profile. The naming restrictions are to avoid parsing editor backup files, .rpmsave files, and the like. If any appropriately named file is unreadable, profile parsing fails.
  +
  +
Include directives may be used within included profile files as well as the original file.
   
 
An included file may add variable assignments to an existing section simply by switching to that section and making variable assignments within it. This functionality already exists within the profile library.
 
An included file may add variable assignments to an existing section simply by switching to that section and making variable assignments within it. This functionality already exists within the profile library.
   
Currently there is no way to remove or replace an existing value from within an included file. This project does not propose to add that functionality, but it could be added in the future.
+
Currently there is no way to remove or replace an existing value from within an included file. This project does not propose to add that functionality.
   
 
Currently, the profile library recognizes when a profile file changes by stat()ing the file on each profile_get_value() call (though no more than once per second). If the file has changed, it is reread. The profile library will not automatically recognize when included files have changed.
 
Currently, the profile library recognizes when a profile file changes by stat()ing the file on each profile_get_value() call (though no more than once per second). If the file has changed, it is reread. The profile library will not automatically recognize when included files have changed.
  +
  +
The profile library has support for writing a profile file to disk using profile_flush() or a similar function. If such a function is used, the profile file's contents will be flattened into one file with no include directives. This is consistent with other limitations of profile_flush() such as not remembering comments.
   
 
==Implementation Design==
 
==Implementation Design==
Line 23: Line 25:
 
static errcode_t parse_file(FILE *f, struct parse_state *state);
 
static errcode_t parse_file(FILE *f, struct parse_state *state);
   
parse_line() recognizes lines beginning with "include" and passes the following text to a new function parse_include().
+
parse_line() recognizes lines beginning with "include" or "includedir" and passes the following text to new functions profile_include_file() and profile_include_dir().
  +
  +
profile_include_file() creates a fresh parsing state sharing the root section with the parent state, and then opens and parses the file.
  +
  +
profile_include_dir() iterates over the directory and includes each validly named file within it.
  +
  +
===Testing===
   
parse_include() uses the POSIX.2 function glob() to expand the pattern into a list of filenames, opens each file, and calls parse_file() to parse its contents into the existing state structure.
 
  +
Tests exercising the include and includedir directives will be added to the existing tcl-based profile tests.
   
==Open Issues==
+
==Rationale==
   
* glob() may not exist on all systems. Does it exist on Windows? If it does not exist, what fallback position should the code take? Options are:
 
  +
* The original version of this proposal included glob pattern support. This was discarded in favor of "includedir" in order to simplify error cases and sidestep any portability issues of relying on the POSIX.2 glob() function.
** Fail to compile if glob() does not exist.
 
** Disable include support if glob() does not exist.
 
** Allow only includes of explicit filenames if glob() does not exist.
 
** Provide a glob() implementation if it does not exist. This may be a substantial amount of code.
 
   
* The syntax "include PATTERN" is simple and clear, but may not be optimal. It could break existing profile files which contain an "initial comment" (any text before the first line beginning with '[') with a line which happens to begin with "include". Also, adding an include directive anywhere other than the beginning of a krb5.conf file would cause earlier versions of krb5 to generate a syntax error. Other syntax options include:
 
  +
* Several syntax options for the include directive were considered, such as "#include FILENAME" (masquerading as a comment to old versions of the library), [include FILENAME] (masquerading as a section name), "@include FILENAME" (not masquerading as anything, but reducing the likelihood of conflicting with an initial comment of an existing profile), and "[libdefaults] include = FILENAME". Rough consensus was that the simple "include FILENAME" was best.
** Masquerade as a comment: #include PATTERN
 
** Masquerade as a section: [include PATTERN]
 
** Distinctive punctuation: @include PATTERN
 
   
* Nothing in the design prevents include directives containing relative paths or patterns. Such an include directive would have unpredictable effects since the current working directory would be different for different invocations of the krb5 library. Should the profile library protect the administrator by restricting include directives to absolute paths? If so, how should it portably recognize an absolute path?
 
  +
* Several options were considered for handling the case of a profile including a relative pathname, since it is not generally useful in production to include a profile path relative to the process's current working directory. Rough consensus was that it was best to ignore the problem; including relative paths can be useful for testing.
   
* Should an include directive ever result in a fatal error? Possible error cases include:
 
  +
* Strict error handling is employed in order to quickly identify cases where included files are readable by root and not other users.
** Including an explicit filename (not a pattern) which does not exist.
 
** Including a pattern which has no matches. Note that it is impossible to distinguish this case from the previous one without breaking the abstraction barrier of glob().
 
** Including a pattern or filename which attempts to descend into directories which the process has no permission to read.
 
** Including a pattern or filename which matches a file, but the file cannot be opened.
 
Note that because of the profile library architecture, it cannot generate extended errors.
 

Latest revision as of 12:37, 27 May 2014

This project was completed in release 1.9.


Background

In a July 2010 mailing list discussion about dynamic module discovery, consensus was reached that the profile library should gain support for include-file functionality with the ability to include a variable set of files within a directory. This project is to add that support.

Interface Design

A profile file may contain a line "include FILENAME". FILENAME is read, and relations from the file are added to the original profile. If FILENAME does not exist or cannot be read, profile parsing fails.

A profile file may include a line "includedir DIRNAME". If DIRNAME does not exist or is unreadable, profile parsing fails. Files within DIRNAME, whose names consist only of alphanumeric characters, dashes, and underscores, are read and their relations added to the original profile. The naming restrictions are to avoid parsing editor backup files, .rpmsave files, and the like. If any appropriately named file is unreadable, profile parsing fails.

Include directives may be used within included profile files as well as the original file.

An included file may add variable assignments to an existing section simply by switching to that section and making variable assignments within it. This functionality already exists within the profile library.

Currently there is no way to remove or replace an existing value from within an included file. This project does not propose to add that functionality.

Currently, the profile library recognizes when a profile file changes by stat()ing the file on each profile_get_value() call (though no more than once per second). If the file has changed, it is reread. The profile library will not automatically recognize when included files have changed.

The profile library has support for writing a profile file to disk using profile_flush() or a similar function. If such a function is used, the profile file's contents will be flattened into one file with no include directives. This is consistent with other limitations of profile_flush() such as not remembering comments.

Implementation Design

All necessary changes can be made within util/profile/prof_parse.c.

The main body of profile_parse_file() needs to be split out to allow parsing a file's contents into an already existing state structure. The new helper function has the signature:

 static errcode_t parse_file(FILE *f, struct parse_state *state);

parse_line() recognizes lines beginning with "include" or "includedir" and passes the following text to new functions profile_include_file() and profile_include_dir().

profile_include_file() creates a fresh parsing state sharing the root section with the parent state, and then opens and parses the file.

profile_include_dir() iterates over the directory and includes each validly named file within it.

Testing

Tests exercising the include and includedir directives will be added to the existing tcl-based profile tests.

Rationale

  • The original version of this proposal included glob pattern support. This was discarded in favor of "includedir" in order to simplify error cases and sidestep any portability issues of relying on the POSIX.2 glob() function.
  • Several syntax options for the include directive were considered, such as "#include FILENAME" (masquerading as a comment to old versions of the library), [include FILENAME] (masquerading as a section name), "@include FILENAME" (not masquerading as anything, but reducing the likelihood of conflicting with an initial comment of an existing profile), and "[libdefaults] include = FILENAME". Rough consensus was that the simple "include FILENAME" was best.
  • Several options were considered for handling the case of a profile including a relative pathname, since it is not generally useful in production to include a profile path relative to the process's current working directory. Rough consensus was that it was best to ignore the problem; including relative paths can be useful for testing.
  • Strict error handling is employed in order to quickly identify cases where included files are readable by root and not other users.